【翻译】6.824 lab2 Raft (自用不负责)
介绍
这是系列实验中的第一个,您将在这些实验中构建容错键/值存储系统。在本实验中,您将实现Raft,一个复制状态机协议。在下一个实验中,您将在Raft之上构建键/值服务。然后,您将在多个复制的状态机上“共享”您的服务,以获得更高的性能。
复制的服务通过将其状态(即数据)的完整副本存储在多个副本服务器上来实现容错。 复制允许服务继续运行,即使其某些服务器出现故障(崩溃或网络故障或故障)。 挑战在于,故障可能会导致副本保存不同的数据副本。
raft将客户请求组织成一个序列,称为日志,并确保所有副本服务器看到相同的日志。 每个副本均以日志顺序执行客户端请求,并将其应用于服务状态的本地副本。 由于所有活动副本都看到相同的日志内容,因此它们都以相同的顺序执行相同的请求,因此继续具有相同的服务状态。 如果服务器出现故障但后来又恢复了,Raft会确保其日志为最新状态。 只要至少大多数服务器处于活动状态并且可以相互通信,Raft就会继续运行。 如果没有这样的多数,Raft将不会取得进展,但是一旦多数能够再次交流,它将从中断的地方继续前进。
在本实验中,您将把RAFT实现为带有关联方法的Go对象类型,以便在更大的服务中用作模块。一组Raft实例通过RPC相互通信来维护复制的日志。您的RAFT界面将支持编号不定的命令序列,也称为日志条目。这些条目用索引号编号。最终将提交具有给定索引的日志条目。届时,您的Raft应该将日志条目发送到较大的服务,以便其执行。
您应该按照扩展的Raft文件中的设计,特别注意图2。您将实现本文中的大部分内容,包括保存持久状态并在节点出现故障然后重新启动后读取它。 您将不会实施集群成员资格更改(第6节)。 您将在稍后的实验中实现日志压缩/快照(第7节)。
您可能会发现本指南以及关于锁和并发结构的建议非常有用。从更广泛的角度来看,请查看Paxos,Chubby,Paxos Made Live,Spanner,Zookeeper,Harp,iewstamped Replication和Bolosky等。
这个实验分三部分完成。
开始实验
如果您已完成实验1,则已经拥有该实验源代码的副本。如果没有,您可以在Lab 1 instructions中找到通过git获取源代码的指导。
我们为您提供框架代码src/raft/raft.go
。我们还提供了一组测试,您应使用这些测试来推动实现工作,并使用它们来对提交的实验进行评分。测试位于src/raft/test_test.go
中。要启动并运行,请执行以下命令。 不要忘记使用git pull
获得最新软件。
$ cd ~/6.824
$ git pull
...
$ cd src/raft
$ go test
Test (2A): initial election ...
--- FAIL: TestInitialElection2A (5.04s)
config.go:326: expected one leader, got none
Test (2A): election after network failure ...
--- FAIL: TestReElection2A (5.03s)
config.go:326: expected one leader, got none
...
$
代码
通过在raft/raft.go
中添加代码来实现Raft。在该文件中,您将找到框架代码,以及如何发送和接收RPC的示例。
您的实现必须支持以下接口,测试人员和(最终)您的键/值服务器将使用该接口。 您可以在raft.go的注释中找到更多详细信息。
// 新建Raft服务器实例:
rf := Make(peers, me, persister, applyCh)
// 启动新日志条目协议:
rf.Start(command interface{}) (index, term, isleader)
// 向raft询问当前任期,以及是否认为自己是领导者
rf.GetState() (term, isLeader)
// 每次将新条目提交到日志时,每个raft peer都应将ApplyMsg发送给service(或测试人员)。
type ApplyMsg
服务调用Make(peers,me,...)
创建一个raft peer。peers参数是用于RPC的raft peer (包括这一个)的网络标识符的数组。me
参数是peers 数组中该peer的索引。Start(command)
请求raft启动处理,将命令附加到复制的日志中。Start()
应该立即返回,而不必等待日志追加完成。该服务希望您的实现将每个新提交的日志条目的ApplyMsg
发送到Make()
的applyCh
通道参数。
raft.go
包含示例代码,该示例代码发送RPC(sendRequestVote())
并处理传入的RPC(RequestVote()
)。您的raft peer应该使用labrpc Go软件包(源代码位于src/labrpc
)交换RPC。测试人员会告诉labrpc
延迟RPC,对其重新排序,以及丢弃它们以模拟各种网络故障。虽然您可以临时修改labrpc
,但请确保您的raft可以与原始labrpc
一起工作,因为我们将使用原始labrpc对您的实验进行测试和评级。您的raft实例必须仅与RPC交互; 例如,不允许他们使用共享的Go变量或文件进行通信。
后续实验建立在本实验的基础上,因此给自己足够的时间来编写可靠的代码非常重要。
Part 2A
任务
实现raft leader 选举和 heartbeats(没有日志项的AppendEntries RPCs).2A 的目标是选出一名leader,如果没有出现故障,该leader将继续担任leader,如果旧leader失败或数据包丢失,则由一名新leader接任。运行go test -run 2A
来测试2A代码