type
status
date
slug
summary
tags
category
icon
password
Lab要求
这个lab是2024年新增,目的可能是想在到raft之前把梯度曲线舒缓一下,相比MapReduce来说较为简单,主要考察了go中map的使用和网络通信的简单设计
但是由于我没有看懂题目,还是被困了很久,现在在这里梳理梳理
在本实验中,您将为单台机器构建一个键/值服务器,以确保每个操作在网络故障的情况下都只执行一次
,并且操作是线性化的。稍后的实验室将复制一台像这样的服务器来处理服务器崩溃。
客户端可以向键/值服务器发送三种不同的 RPC:
Get(key)
- 键和值是字符串,用于安装或替换映射中特定键的值
- 返回值:要求服务器返回该字符串对应的Value,对于不存在的键应返回空字符串。
Put(key, value)
- 键和值是字符串,Put(key, value) 安装或替换映射中特定键的值
没有返回值
,这个地方需要注意,Put是没有返回值的
Append(key, arg)
- Append(key, arg) 将 arg 附加到键的值
- 返回值:返回旧值
每个客户端通过一个与服务器对话 Clerk 使用 Put/Append/Get 方法。一个 Clerk 管理与服务器的 RPC 交互。
到这里就差不多完成Lab的介绍
Key/value server with no network failures
假设网络通信之间没有任何的问题,一切都非常完美,在这种情况下会使用的代码结构
这里很简单,只是需要把server中的方法写好,在client端写好Clerk的调用即可,只要看懂了题目就可以直接写(当然也会因为有些题目没看懂什么意思而被卡住)
然后运行go test完成前两个测试即可
Key/value server with dropped messages
到这里就开始出现涉及丢包的情况,在丢包的情况下key-value server通信会是什么样子
这里涉及到两种情况的丢包:
- Client端丢包
- Client端丢包不会对服务器server造成什么影响,所以直接重发即可,以
Get
函数为例子 - 同时Client端需要维护一个
RequestId
,便于server区分Client端的不同请求
- Server端丢包
- server端丢包相对来说要严重不少,尤其是在存在返回值的时候,这里我们可以发现一个奇妙的现象:
- 对于Get函数,server丢包只需要Client多传输request即可,由于一个client可以看作只对server执行一次操作,所以可以直接不更改
- 对于Put函数,由于不需要返回值,只是进行更改,在一个Client只会进行一种call的情况下,直接对Put不做更改也没问题
- 对于Append函数,需要进行更改
更改的思路是在server端维护一个Map,这个Map作为一个Cache保存
RequestId
对应的Value结果,在出现需要重复执行的情况时,直接返回Map对应的值作为结果。注意在server收到不同的
RequestId
的请求时,会删除前一次的RequestId
请求,我这里对RequestId
的变化只是进行递增Client端
Server端