-
Notifications
You must be signed in to change notification settings - Fork 160
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
Re call add_learner for a restarted node don't sync the state (snapshot). #927
Comments
👋 Thanks for opening this issue! Get help or engage by:
|
You don't need to invoke Once a node has been incorporated into a cluster, no further action is required upon restart. As for the problem regarding logs being replicated but not applied, could you supply the source code of the application and the debug-level logs for us to investigate further? |
Just use raft-kv-memstore example will reproduce the issue. export RUST_LOG=debug
nohup ./target/debug/raft-key-value --id 1 --http-addr 127.0.0.1:21001 > n1.log &
nohup ./target/debug/raft-key-value --id 2 --http-addr 127.0.0.1:21002 > n2.log &
nohup ./target/debug/raft-key-value --id 3 --http-addr 127.0.0.1:21003 > n3.log &
sleep 2
curl "127.0.0.1:21001/init" -H "Content-Type: application/json" -d "{}"
sleep 1
curl "127.0.0.1:21001/add-learner" -H "Content-Type: application/json" -d '[2, "127.0.0.1:21002"]'
sleep 1
curl "127.0.0.1:21001/add-learner" -H "Content-Type: application/json" -d '[3, "127.0.0.1:21003"]'
sleep 1
curl "127.0.0.1:21001/change-membership" -H "Content-Type: application/json" -d '[1, 2, 3]'
sleep 1
curl "127.0.0.1:21001/write" -H "Content-Type: application/json" -d '{"Set":{"key":"foo","value":"bar"}}'
sleep 1
curl "127.0.0.1:21003/read" -H "Content-Type: application/json" -d '"foo"'
curl "127.0.0.1:21001/write" -H "Content-Type: application/json" -d '{"Set":{"key":"foo","value":"zoo"}}'
sleep 1
curl "127.0.0.1:21003/read" -H "Content-Type: application/json" -d '"foo"' Then kill Then restart it wait some seconds and read
As you can see read |
Memstore does not persist data to disk. All state on node-3 will be lost upon restart. And raft does not guarantee the state will be correctly synchronized when there is data loss. In your scenario, the By removing node-3 and then re-add it. The replication state is reset and the leader forgets the previous state about that "logs are already replication to node-3" and starts to re-send all logs. There is a FAQ(not yet published) discussing about this issue(https://github.com/datafuselabs/openraft/blob/main/openraft/src/docs/faq/faq.md):
|
Even if node-3 have disk storage, what if when node-3 received the last-n logs from node-1 and node-3 starting to save the state to disk, at this point node-3 crashed and the last-n logs lost? Is node-1 still see the last-n logs replicated to node-3? I think there maybe need a communication process, if node-3's last log index is small than node-1 should allow node-1 sync state to node-3. If I understand correctly, remove node-3 and re-add node-3 is the only way to sync state from node-1? |
Raft can not provide any guarantee when any data is lost. It's undefined behavior. As I mentioned previously, |
I see. Thanks! |
openraft version:
0.8.3
I have a 3 nodes memory storage cluster setup by following steps:
Then restart node-3 and call
add_learner(3)
for it, I can see node-3 got logs from node-1 but the theapply_to_state_machine()
function not called, so the state is not synced.So, my question is what's the proper way to restart a node and sync state from the leader?
NOTE: If I call change_membership(RemoveNodes([3])) and re-add it, it will works just as expected.
The text was updated successfully, but these errors were encountered: