/raft-demo

通过hashicorp-raft库手把手调试raft协议

Primary LanguageGo

一、Raft协议简介

二、Raft选举过程

  • 选举过程图1(单个节点视角)

选举流程

  • 选举过程图2(整体视角)

选举流程2

三、Raft日志复制流程

  • 日志格式:term + index + cmd + type

日志流程

  • 请求处理整体流程

日志流程

  • 请求处理详细流程(重点)

日志流程

注:这里7. commit log 应该是在5. commit之后,但是因为commit有一定延迟所以从日志上看是在回复客户端以后

四、Raft协议动画演示

五、hashicorp/raft源码讲解

六、运行hashicorp/raft库搭建的简单kv服务

  • 编译:go build -mod vendor

  • 启动node1: ./raft-demo --http_addr=127.0.0.1:7001 --raft_addr=127.0.0.1:7000 --raft_id=1 --raft_cluster=1/127.0.0.1:7000,2/127.0.0.1:8000,3/127.0.0.1:9000

  • 启动node2: ./raft-demo --http_addr=127.0.0.1:8001 --raft_addr=127.0.0.1:8000 --raft_id=2 --raft_cluster=1/127.0.0.1:7000,2/127.0.0.1:8000,3/127.0.0.1:9000

  • 启动node3: ./raft-demo --http_addr=127.0.0.1:9001 --raft_addr=127.0.0.1:9000 --raft_id=3 --raft_cluster=1/127.0.0.1:7000,2/127.0.0.1:8000,3/127.0.0.1:9000

  • set请求:curl http://127.0.0.1:7001/set?key=test_key&value=test_value

  • get请求:curl http://127.0.0.1:7001/get?key=test_key

七、调试场景

选举变化相关
  1. 集群启动后,follower等待一个随机election timeout时间变成candidate,然后发起投票,如果不能获得majority票数,则任期term会一直增加(未pre-vote情况)(branch: election-1)

  2. 集群启动后,follower等待一个随机election timeout时间变成candidate,然后发起投票,获得majority票数的节点变成leader (branch: election-2)

  3. leader选举成功后发送heartbeat保持leader的地位(branch: election-3)

  4. leader失去majority节点的heartbeat响应,退回到follower(branch: election-4)

日志复制相关
  1. leader接收客户端请求,向集群内所有节点发送复制RPC,所有都正常响应 -> 正常commit,然后apply到状态机,最后返回客户端处理成功(branch: replicate-log-1)

  2. leader接收客户端请求,向集群内所有节点发送复制RPC,majority正常响应 -> 正常commit,然后apply到状态机,最后返回客户端处理成功(branch: replicate-log-2)

  3. leader接收客户端请求,向集群内所有节点发送复制RPC,少于majority正常响应 -> 不能commit(branch: replicate-log-3)

八、收获

  • hashicorp/raft源码

  • raft选举与日志复制

九、QA

纠正:3个节点宕机2个,剩下一个不可用,怎么处理请求的强一致?

答:这个时候服务应该是不可用的,当然如果要强行提供查询的服务,强一致肯定是无法保证的。