2021 MIT6.824 Lab2B Raft算法(二):日志复制(log replication)

0 前言

之前的博客中实现了完成了Lab2A,raft的leader选举。这一篇博客讲述Lab2B,日志复制的内容。首先说一下总体感受,这是一个细节爆炸的实现,对论文理解稍有偏差就会导致测试不能通过,所以建议写码之前多读两遍论文,同时阅读一下课程助教写的guide,里面有一些常见的往年学生踩过的坑,特别是多线程下避免竞态,测试时最好加上-race检测。如果还是有困难的话,可以参考一下这篇博客,写得确实很棒。下面说一下算法实现,当然,由于课程有要求,这里就不上代码了。

1 概述

之前也提到过,raft是基于复制状态机的,每一个服务器存储一个包含一系列指令的日志,并且按照日志的顺序进行执行。当leader被选举出来后,这个系统就会对外提供服务。当收到一个客户端指令后,会执行下面的逻辑:

  1. leader将此指令复制到所有服务器中
  2. 确认至少一半以上服务器复制指令后,leader将指令应用到状态机
  3. 响应客户端

这是理想的情况,然而在实际工作的系统将会面临服务器宕机、网络延迟、分区等各种干扰,raft的日志复制将保证所有服务器存储日志一致、应用在状态机上的指令一致。

2 细节实现

2.1 leader

根据figure2,leader通过nextIndex数组和matchIndex数组来完成日志同步与日志提交。nextIndex的含义是leader下一次在心跳包需要发送给follower的日志起始位置(顺便说一下,leader election中讲过leader定期发送心跳包维护权威,如果nextIndex[server]小于leader的日志长度的话,心跳包就会带上日志),如果日志匹配成功,nextIndex[server]更新nextIndex[server] = req.PrevLogIndex + len(req.Entries),如果失败,就nextIndex[server] -= 1,当然这里可以优化,加快回退速度,就是按照论文7、8之间的那个准则(需要为AppendEntriesReply增加三个参数XTerm、XIndex、XLen,具体可以观看课程视频)。
matchIndex则可以帮助leader判断一条日志该不该commit。如果一条日志的下标为N,有一半以上的matchIndex[server] >= N,便可以commit。我在这里实现的时候,单独为leader开了一条线程来检测是否有新的日志需要提交,注意每次扫描之后不要让线程休眠太久,几十毫秒即可。下面说一下checkCommit的算法步骤:

拿到一个rf.matchIndex的副本数组matchId 将它排序
median := matchId的中位数(matchId[len(matchId)/2])
if median > rf.commitIndex && rf.log[median].Term == rf.currentTerm {
	rf.commitIndex = median
}

这个方法效率不错,是我在阅读一篇知乎回答的时候学习到的。

2.2 follower

当follower收到一个AppendEntries请求时,可以根据以下原则去更新与响应。
在这里插入图片描述
日志更新之后,follower会根据leader的commitIndex更新自己的commitIndex然后提交日志,应用到状态机,这里guide也是提示单独使用一个线程,结合cond去做。我在这里实现的时候是这样做的

for server存活 {
	rf.上锁
	for rf.lastApplied == rf.commitIndex {
		rf.cond.Wait() //线程阻塞等待唤醒
	}
	rf.解锁
	更新lastApplied并提交日志
}

当follower更新commitIndex后可以使用Signal唤醒这条线程。

2.3 线程相关

一个raft节点需要开启几个long-running线程?在guide里提示了两个,一个是负责检测是否发生选举超时的线程,一个是负责commit日志的线程。作为leader的话,必须还要有一个发送心跳包的线程,最后一个是如前所述扫描matchIndex更新commitIndex的线程。所以作为普通Follow需要两个long-running线程,leader的话需要4个。利用RPC做通信的话,会有更多的线程参与进来,所以再一次提醒使用好锁。

3 测试结果

在这里插入图片描述

35s的通过时间还算不错,一开始做的时候是一分钟,后来修改了一下心跳时间和选举时间为100ms和300ms到450ms,又修改了一下checkCommit的时间间隔,并且加了nextIndex的优化,速度得到提升。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值