【翻译】6.824 lab2 Raft (自用不负责)

发布时间 2023-06-16 12:33:38作者: Greenty

介绍

这是系列实验中的第一个,您将在这些实验中构建容错键/值存储系统。在本实验中,您将实现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代码

提示