终于到了这个 Lab4,不容易啊。。。
# 4A
a set of replica groups
每一个 replica group 负责一系列 shards。每个 group 就是一个 raft 组
shard master
shard master 负责 shard key 由哪个 group 负责。
shard controller 也必须是 F.T,所以需要使用 Raft。
shardctrler 必须管理一系列 configuration,每一个 configuration 都表述了一组 replica groups 已经将 shard 到 replica 的 assignment。每当 assignment 需要改变的时候,这个 shard controller 就创建一个新的 configuration 进行新的 assignment。KV clients 和 servers 都和 shardctrler 进行沟通,当他们想要新的 configuration(或者旧的 configuration?这里为什么需要旧的)
首先我们需要实现 4 个 RPC,这些列出用于控制 shardctrler,加入新的 replica group 或者清除 replica groups。
Join:用于 replica 的组的加入,参数是 groupID 到 servername 的映射。如果 shardctrler 救助站了这个新的组,那么需要做一个新的 configuration。shardctrler 需要将 shard 切分得尽量均匀 assign 给 replica group。并且需要 move 尽量少的 shard 来到达目标。并且 GID 可以被重用,也就是 GID 允许加入、退出、重新加入。
Leave:leave 就是一些 GIDs。shardCtrler 需要重新创建新的 configuration。这个新的 configuration 需要同样 shards 被 divide 尽量均匀
Move:Move 就是把一个 shard 分配到一个 GID,这个 Move RPC 用于测试。Move 操作之后的 Join 和 Leave 实际上是在对 Move 进行 Undo,因为这两个操作都会重新分配 shard。
Query:query 查询的是一个 configuration number,如果这个 configuration number 不存在,那就返回最大的一直 configuration number 的 configuration。
最开始的 configuration number 为 0,并且不包含任何的 group,所有的 shard 都 assign 给 GID 0.
Hints:
- 可以 copy 之前的 kvraft server。
- 需要过滤重复的 rpc。
- 状态机的 shard rebalancing 需要确定
直接套用 Lab3 带代码:
Test: Basic leave/join ...
... Passed
Test: Historical queries ...
... Passed
Test: Move ...
... Passed
Test: Concurrent leave/join ...
... Passed
Test: Minimal transfers after joins ...
... Passed
Test: Minimal transfers after leaves ...
... Passed
Test: Multi-group join/leave ...
... Passed
Test: Concurrent multi leave/join ...
... Passed
Test: Minimal transfers after multijoins ...
... Passed
Test: Minimal transfers after multileaves ...
... Passed
Test: Check Same config on servers ...
... Passed
PASS
ok 6.824/shardctrler 2.389s
简单 pass 一个。
# 4B
需要修改:
shardkv/client.go , shardkv/common.go , and shardkv/server.go 这三个文件。
replica groups have to hand off shards to each other
可能需要重新设计 4A 的代码,尽量少移动 shard。问题来了,怎么在不同的 raft 组之间移动数据?
必须实现线性一致性,这个可以仿照之前 lab3 来做。
This must be true even when Get s and Put s arrive at about the same time as configuration changes.
这说明 configuration change 完毕的时候,必须是相同的副本,可以简单设计 reconfiguration 时候不处理任何 get 和 put 请求?这个之后再考虑。
Think about how the shardkv client and server should deal with
ErrWrongGroup. Should the client change the sequence number if it receivesErrWrongGroup? Should the server update the client state if it returnsErrWrongGroupwhen executing aGet/Putrequest?
我的设计,当查询到配置变更信息后,立刻加锁进行迁移数据,这样就可以拒绝接受请求和 apply log。完成迁移数据之后再释放锁。对于此后再次 apply 上的 log index,如果此时 server 不负责这个 shard,那么直接丢弃就可以了,也不更新查重表。对于此后如果旧的请求再次到来,如果是 put/append,直接查查重表,即使不负责这个 shard 如果之前做过这个请求,也可以返回 OK。但是之后的之后的请求就会发送 ErrWrongGroup 。
对于新的迁移过去的 shard,查重表初始为 0,对应着任务没有完成,因为这个新的 server 并不会去服务旧的 rpc,所以此时也是可以正常工作的。
(所以 client 的逻辑就是,只有接受到 ErrWrongGroup 的请求才会查询新的配置,防止重复 apply)
After a server has moved to a new configuration, it is acceptable for it to continue to store shards that it no longer owns
即使迁移了一个新的配置,也可以保留原来的数据。
# 3.20 更新
Lab4 + 2Challenge 完美通过,并发测试没有搞,我的电脑配置不支持这个 lab 的批量测试。。。而且我也不想搞了,太心累了
Test: static shards ...
... Passed
Test: join then leave ...
... Passed
Test: snapshots, join, and leave ...
... Passed
Test: servers miss configuration changes...
... Passed
Test: concurrent puts and configuration changes...
... Passed
Test: more concurrent puts and configuration changes...
... Passed
Test: concurrent configuration change and restart...
... Passed
Test: unreliable 1...
... Passed
Test: unreliable 2...
... Passed
Test: unreliable 3...
... Passed
Test: shard deletion (challenge 1) ...
... Passed
Test: unaffected shard access (challenge 2) ...
... Passed
Test: partial migration shard access (challenge 2) ...
... Passed
PASS
ok 6.824/shardkv