开源之夏经验分享|SOFAStack 社区 袁梓为:开源项目从不是遥不可及

84c483718103f553ef45893e02933b6d.gif

本篇项目经验分享来自 SOFAStack 社区中选学生——袁梓为,在开源之夏 2023 中承担的项目是结合 NWR 实现 Flexible Raft,用于自定义 Quorum 的大小。

680be0c3eba8832d6ce5efa5044739dd.png

关于 SOFAStack 社区

SOFAStack™(Scalable Open Financial Architecture Stack)是一套用于快速构建金融级云原生架构的中间件,也是在金融场景里锤炼出来的最佳实践,并且具备以下特点:

  • 开放:技术栈全面开源共建、保持社区中立、兼容社区、兼容开源生态,组件可插拔,SOFAStack 组件与其它开源组件可相互集成或替换;

  • 金融级:包含构建金融级云原生架构所需的各个组件,让用户更加专注于业务开发,满足用户场景的现状和未来需求,经历过大规模场景的锤炼,特别是严苛的金融场景;

  • 云原生:基于 SOFAStack 可快速搭建云原生微服务体系,快速开发更具可靠性和扩展性、更加易于维护的云原生应用。

官网:https://www.sofastack.tech/

项目基本信息

项目名称:结合 NWR 实现 Flexible Raft,用于自定义 Quorum 的大小

项目导师:刘源远

项目描述:SOFAJRaft 是一个基于 Raft 一致性算法的生产级高性能 Java 实现,它运行过程分为两个阶段,即 Leader 选举和日志复制。

在原始的 Raft 算法中,Leader 选举和日志复制都需要获得多数派成员的支持。而 NWR 模型则可以在动态调整一致性强度的场景中使用,它需要满足 W+R>N,以保证强一致性。JRaft 将 Raft 和 NWR 结合起来,使得用户可以根据不同的业务需求来动态调整 Quorum 的数量。

例如,在一个写多读少的场景中,用户可以将多数派的数量从 3 调整为 2,以降低达成共识的条件,从而提高写请求的效率。同时,为了保证 Raft 的正确性,写 Quorum 的调整需要付出代价,即读 Quorum 的数量也需要相应调整。JRaft 支持成员变更,因此用户可以配置 (0,10] 范围内的数来计算 W 和 R 的具体值(需要满足 W+R=10)。通过使用 Flexible JRaft,用户可以根据自己的业务需求来灵活地调整一致性强度,使得分布式系统在不同场景下都可以获得最佳的性能和正确性。

项目链接:https://summer-ospp.ac.cn/org/prodetail/2395a0390

项目实现思路

为了更清晰地展示 NWR 是如何与 JRaft 结合的,我们这里避免繁琐的代码细节展示,试着用简单的图片来体现他们之间的联系。

我们知道,NWR 是一种在分布式存储系统中用于控制一致性级别的策略。N 在分布式存储系统中,代表有多少份备份数据 。W 代表一次成功的更新操作要求至少有 W 份数据写入成功。R 代表一次成功的读数据操作要求至少有 R 份数据成功读取。

例如,在一个 N=3 的 Raft 集群中,W 是 2、R 是 2 的时候,W+R>N,这种情况对于集群而言就是强一致性的。

7b5e3cfedef0830b7f80de9e682a386c.png

而当 R+W<=N 时,无法保证数据的强一致性。因为成功写和成功读集合可能不存在交集,这样读操作无法读取到最新的更新数值,也就无法保证数据的强一致性。例如下图中 W=2,R=1 的时候,W+R=3=N 满足不了强一致性。

2f131995d92f69106543c7f53b1afcc5.png

在分布式一致性算法 Raft 中,Configuration(配置)是用于管理集群成员和集群状态的一组信息。每个服务器节点都有一个配置,用于确定当前集群的成员身份和状态。

所以,我们能否将 Quorum 交给 Configuration 来管理呢?随着 Configuration 的集群成员信息变化,ReadQuorum 与 WriteQuorum 也随之变化,这样我们对于 Quorum 的管理也更加灵活方便。在 Configuration 中也持有当前 Raft 集群的模式标志,用来表示当前集群是 Majority 模式还是 Flexible 模式。另外,除了节点配置信息的持久化,我们同样也要对 Quorum 进行持久化。所以,Quorum 放到 Configuration 之后,将随着集群配置信息一同进行持久化。

68ec5a4500b7d9c699ab785bd7ec4ddb.png

在设计好 Quorum 之后,接下来需要考虑哪些地方需要对 Quorum NWR 模型进行适配。在 Raft 算法中,会牵涉到选票的模块有:选举、日志复制、一致性读与成员变更。所以,对于这些模块,我们都需要兼容以往的多数派投票逻辑(Majority 模式),并且在这基础上去适配新的 Flexible 模式。

3e357ba1cfe645d3da110d470dd2cf34.png

接下来我们简单阐述以上四个模块对于 NWR 模型的适配规则:

Leader 选举模块: 一个节点想要成为 Leader,会经过以下几个阶段:预投票、正式投票、当选 Leader。所以对于 preVote、electSelf、becomeLeader 等等与多数派模型相关的方法都会涉及代码的变更。

日志复制模块: 当 Leader 收到客户端的事务请求或者 Follower 与 Leader 数据存在差距时,会调用 Replicator#sendEntries 去复制日志,日志复制消息属于事务消息;而心跳消息和探测消息,则是由 Replicator#sendEmptyEntries 发送的。

在日志复制中,部分代码会使用到 BallotBox#appendPendingTask 方法来构造一个待投票的 Ballot 并放置到投票箱中,所有复制过程中参与投票的方法都需要对 NWR 进行适配。

一致性读模块: 对于一致性读模块,在 Raft 共识算法中,读取 R 个节点其实体现在 R 个节点的心跳响应。通过 R 个节点的心跳,能保证这个节点一定是当前的 Leader,所以一定拥有最新的数据,因此我们只需要保证 R 个心跳的相应即可。

对应的修改部分,像 NodeImpl#ReadIndexHeartbeatResponseClosure 这样的方法,我们可以看到执行了心跳消息的多数派确认模型的逻辑,ReadIndexHeartbeatResponseClosure 构造器里面传入了 Quorum 的值,这里我们同样需要进行修改。

成员变更模块:对于 JRaft 成员变更来讲,核心逻辑是采用单成员变更的方式,即使需要同时变更多个成员时,也是会先整理出新 add 与新 remove 的成员,再逐个进行单成员变更。其核心方法 addPeer、removePeer、changePeers、resetPeers 等等都会涉及 NWR 模型的适配。

我们的代码基于以上的思路进行设计,有很多的细节处理在实现过程中并不容易做好。在最后还要书写测试用例,跑通所有测试,进行 Jepsen 一致性检验等等工作。

开源之夏个人随访

参与开源之夏和开源

OSPP:请简单介绍一下自己,并分享一下自己的开源经历吧。

袁梓为:大家好,我叫袁梓为,是广东工业大学计算机科学与技术专业大三的一名学生。之前有过一段 Apache RocketMQ 社区的开源经历,主要做的是 RocketMQ-5.0 客户端 SDK 与 Spring 的集成[1];过去也有在 SOFAJRaft 项目中有代码贡献。

OSPP:这是你第一次参与开源之夏,为什么选择参加这个活动?

袁梓为:参加开源之夏既是兴趣,亦是挑战。作为学生,能够接触到开源社区,无疑能够磨练我们的技术,也能够接触到最新的行业动态。开源之夏为学生提供了一个学习、实践和参与开源社区的宝贵机会。这对于技术成长、职业发展以及与开源社区建立联系都具有重要意义。

OSPP:为什么会选择申请 SOFAStack 社区的项目?有为申请项目而提前做什么沟通和准备么?

袁梓为:选择申请 SOFAStack-SOFAJRaft 社区项目的初衷,其实是希望能够深入地学习 Raft 算法。当时正好有做 MIT6.824 的想法,不过考虑到自己主语言是 Java,刚好 SOFA-JRaft 又是基于 Java 实现的生产级高性能 Raft 算法。所以看到项目要求是结合 Quorum NWR 模型实现更加灵活的 Raft 算法时,我就产生了浓厚的兴趣。

其实在大一的时候我有关注过 SOFAJRaft 社区,不过当时能力远远还没有达到能够贡献代码的水平,所以只是每天逛逛社区,尝试着去理解源码。在大二上学期阅读 JRaft 源码的时候,偶然注意到 JRaft 所使用的 Netty 时间轮算法部分涉及循环的代码可以优化,于是提交了我开源世界里的第一个 issue:The problem of Low Efficiency and Multiple Cycles In the TimeWheel Algorithm[2],虽然只是很小的一个 PR,但也算作我迈向开源社区的第一步吧。

在有了一次代码合并经历之后,我也大致懂得了在社区做开源的流程。之后也会时常关注社区的动态,于是在后面又尝试着解决了社区里的另一个小需求:Auto Commit Mode for Applying Log Iterator[3]从刚开始接触一个陌生的社区,到最后参加 JRaft 的开源之夏活动,会发现其实参与开源项目也并不是想象中的那么遥不可及。所以当我有了做 SOFAJRaft 选题的想法后,就立刻与源远导师沟通,源远哥也十分积极地回应,与他交流我对选题的思考。

OSPP:在开发过程中有遇到什么困难或挑战么?你是如何克服困难解决这些问题的?

袁梓为:开发中确实有遇到一些困难和挑战。

比如当初在对 Quorum 类进行设计时,遇到不少坑,如果不考虑好他的构造设计与动态变更的情况,程序运行过程中很容易出错。刚开始我是基于⼀个抽象类,去设计两个 Quorum ⼦类,分别代表 MajorityQuorum 和 FlexibleQuorum,即是多数派模型和 NWR 模型的区别。但是后来发现这两个 Quorum 的区别只是 W 和 R 的计算规则不同,其实我们完全可以⽤⼀个⼯⼚对这两个 Quorum 的读写数值进⾏不同的计算。在经过⼀系列的测试与调整后,最终我们选择了只使⽤⼀个 Quorum 进⾏处理,这个 Quourm 内部包含有 W 和 R 两个属性,他们的计算规则依靠 BallotFactory 来进⾏,最后我们只需要把 Quorum 和 factor 整合到 Configuration ⾥⾯即可。

除了这个问题以外,由于要对 Flexible Raft 进行线性一致性验证,SOFAJRaft 需要用到 Jepsen 框架进行校验。然而这个框架是用 Clojure 语言书写,之前从没有接触过这门语言,所以我也是花了一段时间去学习 Clojure 语法、理解 Jepsen 框架。在大概理解了 JRaft-Jepsen 的校验原理后,还需要自己搭建一个测试环境。因为并没有现成的测试平台可以使用,于是我又用 Docker 模拟 Ubuntu 环境下的多节点去进行验证。这个过程中,也遇到了很多麻烦:比如 Ubuntu 容器之间如何进行 SSH 免密登录通信、容器内依赖工具缺少导致的一系列问题。这些问题要是没处理好,都会影响最后的检验效果。当然这些比较棘手的问题,在向源远导师请教、反复查阅资料、自己不断试错之后,还是得到了解决。

OSPP:导师和社区有为你带来哪些帮助?

袁梓为:在整个开发过程中,有遇到任何难点与困惑点,源远导师都会特别耐心地解答。在某些代码设计上有不妥的地方,源远哥也会指导我如何更优雅地去实现它。社区的其他导师也会积极回应我的留言,在整个开发过程里,提供了非常大的帮助,也让我学到了很多有用的东西。

参与开源社区

OSPP:在你眼中,SOFAStack 是一个怎样的社区?

袁梓为:SOFAStack 社区是一个致力于推动云原生技术发展的开源社区。它通过开源合作、技术创新和社区生态系统建设,为开发者提供了丰富的资源和平台,促进了云原生应用的普及和应用。

OSPP:你在开源社区中是否有超出预期的收获?

袁梓为:我在参与 JRaft 项目的开发中,深入学习和实践了 Raft 算法。通过阅读源码、与导师沟通请教,解决了不少实战开发中遇到的问题。这段经历将是编程道路上宝贵的财富。

寄语

OSPP:参与开源之夏对你的专业技能提升和未来发展规划有带来哪些帮助么?

袁梓为:通过参与开源之夏,我得到了经验丰富的导师的指导和支持,他们提供宝贵的反馈和指导,帮助我解决问题、优化代码,并培养良好的软件开发实践。我还积累到了实践项目经验,并在开源社区中做出有意义的贡献。这些实践和贡献对于我们的职业发展具有积极影响,还能够增加就业的竞争力

OSPP:有什么话想对计划参加开源之夏活动的学弟学妹们说?

袁梓为:我们可以充分利用这段时间,深入学习所选项目的技术栈和开发流程,并积极参与实践。通过解决问题、编写代码和与导师、社区成员交流,获得宝贵的经验和技能提升。

相关链接:

[1] https://github.com/apache/rocketmq-spring/pull/554

[2] https://github.com/sofastack/sofa-jraft/issues/926

[3] https://github.com/sofastack/sofa-jraft/issues/957

本周推荐文章

baee52c032748527eb318e81bb170e0d.png

SOFAJRaft 在同程旅游中的实践

c36a6fce14c5519d3e918b0da0f023af.png

新一代日志型系统在 SOFAJRaft 中的应用

8631cb8a401a58dcb54761cca0e6cf79.png

SOFAStack 的下一个五年

a821e52fb8634268504758d8fb9bafbe.png

MoE 系列(四)|Go 扩展的异步模式

726b15713ded689a30b39ac9e9f1b5d6.jpeg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值