-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
raftstore: use read index to serve read request #1642
Conversation
PTAL |
Please fix the conflict. |
src/raftstore/store/peer.rs
Outdated
}); | ||
self.raft_group.advance_apply(res.apply_state.get_applied_index()); | ||
self.mut_store().apply_state = res.apply_state.clone(); | ||
if has_split { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should use blank to separate the different logic.
term: self.term(), | ||
renew_lease_time: Some(renew_lease_time), | ||
}; | ||
let mut req = RaftCmdRequest::new(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if we send an invalid request, seem that we will log an error when apply the error, it is a little strange.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, this command should be filtered by stale epoch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So we will log an info message for it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes.
// update leader lease. | ||
|
||
let uuid = Uuid::new_v4(); | ||
if self.proposals.contains(&uuid) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seem it is a bug for the uuid lib if we have already had a same uuid.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In contrast, with version 1 and 2 UUIDs using randomly-generated node ids, hash-based version 3 and 5 UUIDs, and random version 4 UUIDs, collisions can occur even without implementation problems, albeit with a probability so small that it can normally be ignored.
https://en.wikipedia.org/wiki/Universally_unique_identifier#Collisions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
got it
PTAL |
c8e7234
to
fc5dc45
Compare
src/raftstore/store/peer.rs
Outdated
@@ -690,6 +723,17 @@ impl Peer { | |||
|
|||
let mut ready = self.raft_group.ready_since(self.last_ready_idx); | |||
|
|||
if ready.ss.as_ref().map_or(false, |s| s.raft_state != StateRole::Leader) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extract this to a function
src/raftstore/store/peer.rs
Outdated
@@ -779,6 +823,31 @@ impl Peer { | |||
} | |||
} | |||
|
|||
let mut propose_time = None; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extract to a function
for (req, cb) in read.cmds { | ||
self.handle_read(req, cb); | ||
} | ||
propose_time = Some(read.renew_lease_time); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need to reduce pending_reads.ready_cnt here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ready_cnt
is zero if this line is reached.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but I only see setting ready_cnt to 0 in L839
for (req, cb) in read.cmds { | ||
let uuid = util::get_uuid_from_req(&req).unwrap(); | ||
apply::notify_stale_req(tag, term, uuid, cb); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need to set ready_cnt to 0 here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, committed reads can still be handled.
PTAL @hhkbp2 |
src/raftstore/store/peer.rs
Outdated
@@ -564,10 +598,9 @@ impl Peer { | |||
send_to_quorum_ts + self.cfg.raft_store_max_leader_lease | |||
} | |||
|
|||
fn update_leader_lease(&mut self, ready: &Ready) { | |||
fn on_role_changed(&mut self, ready: &Ready) { | |||
// Update leader lease when the Raft state changes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comments should be updated when the function changes with its name modified.
return false; | ||
} | ||
// TODO: add it in queue directly. | ||
return Ok(RequestPolicy::ReadIndex); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly maybe it should check commit_index == current term
here and return ProposeNormal
since raft will drop the request directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, this pr's goal is to avoid propose read request. No matter if commit_index
is equal to current term or not, this is handled properly in read_index
.
@@ -139,6 +163,14 @@ pub struct ConsistencyState { | |||
pub hash: Vec<u8>, | |||
} | |||
|
|||
enum RequestPolicy { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's nice to add some comments for each policy to describe briefly what/how is a local read, read index request, consistent read, consistent write, etc., since it helps to understand and these terms lives in related comments.
src/raftstore/store/peer.rs
Outdated
@@ -599,6 +640,13 @@ impl Peer { | |||
self.get_store().committed_index() == self.get_store().applied_index() | |||
} | |||
|
|||
#[inline] | |||
pub fn ready_to_handle_read(&self) -> bool { | |||
// If committed_index doesn't equal to applied_index, written apply state may be overwritten |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comments doesn't match the code, it's possible that the committed_index != applied_index
while applied_index_term == self.term()
.
for state in &ready.read_states { | ||
let read = &self.pending_reads.reads[self.pending_reads.ready_cnt]; | ||
assert_eq!(state.request_ctx.as_slice(), read.uuid.as_bytes()); | ||
self.pending_reads.ready_cnt += 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should record state.index
for the read request, and check this state.index
before performing read, after the log entry of this index is applied.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any update?
tests/raftstore/test_lease_read.rs
Outdated
|
||
// Check if the leader does a consistent read and renew its lease. | ||
// Check if the leader also propose an entry renew its lease. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/renew/to renew/
tests/raftstore/test_lease_read.rs
Outdated
let state: RaftLocalState = engine.get_msg_cf(storage::CF_RAFT, &state_key).unwrap().unwrap(); | ||
assert_eq!(state.get_last_index(), last_index + 1); | ||
|
||
// wait some time to make the proposal to be applied. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/to make/for/
@@ -107,21 +127,20 @@ fn test_renew_lease<T: Simulator>(cluster: &mut Cluster<T>) { | |||
cluster.cfg.raft_store.raft_log_gc_threshold = 100; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those comments in this file need to be updated, since a "consistent read" has change from "write a raft log to raft quorum" to "handle a read index request by cluster with ReadOnlyOption::Safe
option enabled".
Rest LGTM |
self.raft_group.read_index(uuid.as_bytes().to_vec()); | ||
|
||
let pending_read_count = self.raft_group.raft.pending_read_count(); | ||
let ready_read_count = self.raft_group.raft.ready_read_count(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
checking pending_read_count or ready_read_count only is enough?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. The message may be either marked as ready immediately or pushed to pending queue.
Ping |
LGTM |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@siddontang @hhkbp2 PTAL |
LGTM |
1 similar comment
LGTM |
Signed-off-by: Ray Yan <yming0221@gmail.com>
This pr is a clean version for #1628. Original version has too much conflict with master, so I rewrite it again.
@siddontang @hhkbp2 @zhangjinpeng1987 PTAL