Replies: 2 comments 1 reply
-
Thanks for raising this question, but I do not see any issue. It's good to dig into the source code, but you'd better understand linearizability beyond the source code, or from its definition (refer to https://en.wikipedia.org/wiki/Linearizability). A history is linearizable if there is a linear order σ of the completed operations such that:
The first point above specifically addresses Serializability. For a more detailed understanding of this concept, please refer to this example, which explains it thoroughly. The second point addresses read-after-write consistency. It guarantees that the result of a write operation will be visible to subsequent read operations, but only if the reads are issued after the write operation has been completed and acknowledged. I think that this might be what you missed. Serializability is a concept traditionally associated with database systems, ensuring that concurrent transactions yield results equivalent to some serial order. Linearizability, on the other hand, originates from distributed systems, ensuring that operations appear to occur instantaneously in some global order, and is often considered a stricter model in terms of real-time ordering. However, with many modern database systems also being distributed, the distinction between these concepts is less clear, and they often overlap in practice. |
Beta Was this translation helpful? Give feedback.
-
Thank you all for your responses!
This cleared up the question that had been bothering me for days. That linearizability emphasizes the point when an operation is considered complete. The time bounds of linearizability ensure that any changes become visible to other participants only after the operation has finished. This means that each read reflects a current state between the invocation and completion of the operation.
|
Beta Was this translation helpful? Give feedback.
-
Problem Description:
I've encountered a scenario while working with the ETCD Read Index that I believe might expose a potential flaw in the
linearizableReadNotify
mechanism. However, I am not entirely certain if my understanding is correct, and I would greatly appreciate any insights or clarifications from the community.Consider the following scenario where three requests are sent almost concurrently to an ETCD cluster with three nodes. All three requests are targeted to the same key, and the key is initially set to v1, both the leader and followers have an
apply index
of 100 and acommit index
of 100.goroutine-1
initiates a linearizable read by callinglinearizableReadNotify
, targeting the follower node.goroutine-2
proposes a write to change the key's value to v2, targeting the leader node.goroutine-3
initiates another linearizable read by callinglinearizableReadNotify
, also targeting the same follower node asgoroutine-1
.All three requests arrive in sequence, but they arrive at the cluster very close in time.
The sequence of operations is as follows:
goroutine-1
sends a signal toreadwaitc
and begins waiting for thereadNotifier
to be notified. This triggers thelinearizableReadLoop
to request the currentcommit index
from the leader.goroutine-2
proposes a written request, and the leader records such change to the raft log (unstable). Then try to broadcast the log to followers.goroutine-3
finds thatreadwaitc
is blocked and falls back to waiting on the samereadNotifier
instance asgoroutine-1
due to the near-simultaneous arrival of their requests. (A Read lock doesn't stop two goroutines claiming on the same resource)read index
request. and after broadcasting heartbeats to the majority of the cluster members to confirm the leader status, it replies with itscommit index
as 100 (since the write propose has not been confirmed by the majority of the cluster yet).goroutine-2
's write operation successfully replicates the write to a majority of the nodes, advancing the leader'scommit index
to 101. However, these logs are only replicated, and not yet applied to the followers.goroutine-1
andgoroutine-3
, after being notified that the followerapply index
(100) is at least as high as theread index
(100), proceed to read the key's value. Both retrieve the old value v1 from the follower.Issues Identified:
goroutine-3 Reads Stale Data: Although
goroutine-3
is initiated aftergoroutine-2
, it still reads the old value v1. This contradicts the linearizability guarantee, asgoroutine-3
should have observed the updated value v2 given that the write bygoroutine-2
logically precedes it.Commit Index Update Timing: Even if the leader's
commit index
had updated to 101 before theread index
request fromgoroutine-1
andgoroutine-3
, they would both read the new value v2. However, this would violate the linearizability guarantee forgoroutine-1
, which should observe the value v1.Related code (simplified)
Beta Was this translation helpful? Give feedback.
All reactions