mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
raft: support safe readonly request
Implement raft readonly request described in raft thesis 6.4 along with the existing clock/lease based approach.
This commit is contained in:
22
raft/node.go
22
raft/node.go
@@ -60,11 +60,11 @@ type Ready struct {
|
||||
// HardState will be equal to empty state if there is no update.
|
||||
pb.HardState
|
||||
|
||||
// ReadState can be used for node to serve linearizable read requests locally
|
||||
// ReadStates can be used for node to serve linearizable read requests locally
|
||||
// when its applied index is greater than the index in ReadState.
|
||||
// Note that the readState will be returned when raft receives msgReadIndex.
|
||||
// The returned is only valid for the request that requested to read.
|
||||
ReadState
|
||||
ReadStates []ReadState
|
||||
|
||||
// Entries specifies entries to be saved to stable storage BEFORE
|
||||
// Messages are sent.
|
||||
@@ -102,7 +102,7 @@ func IsEmptySnap(sp pb.Snapshot) bool {
|
||||
func (rd Ready) containsUpdates() bool {
|
||||
return rd.SoftState != nil || !IsEmptyHardState(rd.HardState) ||
|
||||
!IsEmptySnap(rd.Snapshot) || len(rd.Entries) > 0 ||
|
||||
len(rd.CommittedEntries) > 0 || len(rd.Messages) > 0 || rd.Index != None
|
||||
len(rd.CommittedEntries) > 0 || len(rd.Messages) > 0 || len(rd.ReadStates) != 0
|
||||
}
|
||||
|
||||
// Node represents a node in a raft cluster.
|
||||
@@ -151,11 +151,6 @@ type Node interface {
|
||||
// Read state has a read index. Once the application advances further than the read
|
||||
// index, any linearizable read requests issued before the read request can be
|
||||
// processed safely. The read state will have the same rctx attached.
|
||||
//
|
||||
// Note: the current implementation depends on the leader lease. If the clock drift is unbounded,
|
||||
// leader might keep the lease longer than it should (clock can move backward/pause without any bound).
|
||||
// ReadIndex is not safe in that case.
|
||||
// TODO: add clock drift bound into raft configuration.
|
||||
ReadIndex(ctx context.Context, rctx []byte) error
|
||||
|
||||
// Status returns the current status of the raft state machine.
|
||||
@@ -370,8 +365,7 @@ func (n *node) run(r *raft) {
|
||||
}
|
||||
|
||||
r.msgs = nil
|
||||
r.readState.Index = None
|
||||
r.readState.RequestCtx = nil
|
||||
r.readStates = nil
|
||||
advancec = n.advancec
|
||||
case <-advancec:
|
||||
if prevHardSt.Commit != 0 {
|
||||
@@ -516,12 +510,8 @@ func newReady(r *raft, prevSoftSt *SoftState, prevHardSt pb.HardState) Ready {
|
||||
if r.raftLog.unstable.snapshot != nil {
|
||||
rd.Snapshot = *r.raftLog.unstable.snapshot
|
||||
}
|
||||
if r.readState.Index != None {
|
||||
c := make([]byte, len(r.readState.RequestCtx))
|
||||
copy(c, r.readState.RequestCtx)
|
||||
|
||||
rd.Index = r.readState.Index
|
||||
rd.RequestCtx = c
|
||||
if len(r.readStates) != 0 {
|
||||
rd.ReadStates = r.readStates
|
||||
}
|
||||
return rd
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user