help wantedhigh priority
描述
背景:
目前 jraft 日志复制基于普通 RPC 的一请求一响应模型,在 RPC 层之上实现了日志的 pipeline 复制,这给上层带来了复杂的控制逻辑,比如要绑定线程以保证发送和接收顺序,要维护一个 inflights FIFO 队列来保证顺序,我们还为此专门实现了一个 MpscSingleThreadExecutor (多生产者单消费者线程池)来提高性能,等等,以上种种,核心原因还是因为受到
一请求一响应的模型的约束从而带来的实现复杂度。
目标:
当前,jraft 有一层 rpc 层的抽象层,并且在去年我们也支持了 grpc,所以我们是否可以利用 grpc 的 streaming 来实现一个新的 AppendEntries,如果抛开一请求一相应的模型,可能有如下好处:
- 可以解除对 jraft 上层实现的高复杂度 pipeline 实现的依赖,极大的简化日志复制逻辑,让日志复制流程简单清晰
- 可能会减少 bug,虽然这一块目前为止基本上没什么 bug,但也遇到过因为心跳进入了 inflights 队列而导致被排序从而心跳超时
- 我们可以尝试合并 AppendEntries Response 来尽可能的减少网络开销和 leader 的处理逻辑开销,这个合并是指 follower 直接取消前边的 response, 只响应最新的 AppendEntries Request 即可,因为实际上 leader 只要收到最后一个 response 就足够了(leader 只是需要对应 follower 最新的 lastLogIndex 而已),当然,这个想法还需要要很多的正确性测试和效果验证,这个不是我创造的想法,更多来自这里 #500
我们需要做什么?
这个任务需要拆开为多个子任务,可能由多个人来实现,目前我们可以先尝试完成第一个任务,后面的任务需要更多细节设计,还需要再考虑。
- 1. 首先,我们要在 rpc api 中新增 streaming 接口(
RpcClient,RpcServer),然后基于 grpc 实现之,对于 bolt 我们可以选择暂时不支持该能力,我觉得这可以作为一个新手任务,欢迎大家认领 - 2. 抽象出
Replicator,将现有的 Replicator 作为默认的一种实现 - 3. 基于 streaming API 实现一个崭新的 Replicator,我们可以将这个特性基于 SPI 扩展,使用哪种 Replicator 由用户选择
- 4. 要通过所有 jraft 单测以及 jepsen 验证
- 5. 最后,要有一个 benchmark 证明我们前面的工作没白费