Vector Clocks
Let's inspect what vector clocks are and how they work and satisfy strong clock condition. Let's also look at the main limitation of Lamport clocks.
Limitation of Lamport clocks
The main limitation of Lamport clocks is that they do not satisfy the strong clock condition. This means they cannot be used to infer causal relationships between events.
The underlying reason for this is that both the local and the global logical clocks for each node are flattened into a single number, which does not provide all the necessary information to track causal relationships.
So we need to maintain a set of all events that causally precede each event. This is known as a
Defining vector clock
A vector clock is another type of logical clock, where the clock data structure for each node is a vector of counters , where is the number of nodes in the system. For the clock of the node :
- The element of the clock represents the local logical clock of the node
- The remaining elements of the clock together form the global logical clock of the node
Rules of the protocol
The rules of the protocol are the following:
- (R1) Before executing an event (send, receive, or local), a node increments the counter of its logical clock by one: .
- (R2) Every sent message piggybacks the clock value of its sender at sending time. When the node receives a message with a vector from the node, it executes the following actions:
- Executes R1
- Updates each element in its vector by taking the maximum of the value in its own vector clock and the value in the vector in the received message: for every in
- Delivers the message
Strong clock condition
Vector clock satisfies the strong clock condition. This means that if the relationship Ci<Cj holds for two events , with timestamps , then .’
The only missing thing is how comparing vector clocks with each other, which is done in the following way:
- For two clocks and iff all the elements of the clock are less than or equal to all the corresponding elements of clock for all and there is at least one element of that is strictly smaller than the corresponding element of for at least one in .
Working of vector clocks
The following illustration contains the same distributed execution displayed in the Lamport clocks lesson’s illustration. This time, we are using vector clocks.
Each node in the system maintains a vector clock, where the first element corresponds to the time in node , the second to the time in node , and the third and last element to the time in node .
We can spend some time again verifying that the clock values have been assigned just by following the rules described above.
This time, we can see that the clock of is smaller than the clock of , while also .
What’s more important, though, is that we can detect events that are not causally related. For instance, and we can see that the timestamp of is neither smaller nor larger than the timestamp of . This means that we can consider these events concurrent, and they could have happened in any order.
Usage of vector clocks
Vector clocks can be used in cases that benefit from the capability to detect whether two events are causally related or concurrent. They also allow the different nodes of the system to make progress independently and efficiently without synchronization and coordination bottlenecks.
Points to be noted
We mentioned previously that in a distributed system of nodes, each vector clock is composed of elements. It’s important to clarify that every process that consists of a source of concurrency needs to be considered as a node of the system in the context of the vector clocks. This means an entry for this process should be dedicated in each clock.
For example, if our application consists of three servers and two clients, each vector clock should contain five entries. Otherwise, we risk not being able to identify concurrent and conflicting operations, and treating them as causally related instead.
It has been formally proven by
Get hands-on with 1400+ tech skills courses.