外观
工程化实现
约 893 字大约 3 分钟
2025-01-28
功能分析
完成一个基于Multi-Paxos的工程化可使用的,可自定义状态机的一致性框架。
可以不断协商确定一系列值,并不断更新状态机的状态。
Paxos算法职责抽象类
实现Paxos协议需要用到的对象根据职责进行抽象。
- Proposer角色类,主要承担提案的Prepare和Accept流程的发起。
- Acceptor角色类,主要承担对Proposer角色类发起的Prepare和Accept请求进行响应。
- Learner角色类,主要负责对已选定提案的获取。
Paxos算法工程化职责抽象类
- Node对象,主要负责将Paxos算法职责抽象类的三类对象融合成一个统一的对象进行管理(进行初始化等生命周期的管控), 包含各类配置信息,以及存储、通信等对象的管理。
- RpcService对象,主要承担协议中的网络传输任务。
- LogEntity对象,主要包装Paxos日志。
- LogStorage对象,主要承担日志在磁盘的持久化存储。
- StateMachine对象,主要承担利用一致性日志对状态机进行状态的变更。
工程化实现的相关问题
将Paoxs协议工程化实现,需要解决逻辑推导阶段的一系列保留问题,问题如下:
- 需要能分布式的产生一个全序的提案编号,编号Mn采用两段式,[自增编号,利用Mac转换的节点编号]。 优先利用自增编号判断大小,其次利用节点编号判断大小。
- Rpc通信问题,使用Netty框架实现各节点之间的通信问题。
- Paxos协议角色的收拢,将各个对象放到一个服务节点上,使用Node管理。
- 日志存储问题,采用LevelDB的开源实现来完成日志持久化。
- Paxos服务节点的崩溃与恢复,需要Acceptor在Prepare和Accept时,完成对响应提案(此时包括自增编号和提案节点Id)的持久化。
- 状态机StateMachine的状态恢复问题,采用快照+日志重放实现。
- 多值商定问题,由于Paxos只能确认一个值,所以引入InstanceId,通过InstanceId的自增来完成一轮轮值的商定, InstanceId相同的实例才可进行同一轮的商定,低InstanceId的实例会通过Learner学习赶上缺失的日志。
工程化实现的参考
PhxPaxos(微信团队)是工程化实现的主要参考,由于笔者主攻java,因此使用58参照PhxPaxos的java实现——WPaxos来进行解析。
此处引用微信团队对PhxPaxos的解析文章:
PhxPaxos文章
Leader虚角色
PhxPaxos引入了Leader的概念,Leader不同于Raft协议的Master。
Leader实际是通过Prepare对Acceptor的一段时间的占有,以减少不断覆盖Prepare阶段,无法达成Accept的情况。
当然也可以引入随机时间来解决这个问题,但是Leader占有更加高效。
当Proposer1对Acceptor1发起Prepare之后,会开启skip阶段,之后下一个值的商定Proposer1可以跳过Prepare阶段。
当Proposer2发起了一个更改编号的提案,Proposer1的Accept就会被拒绝,此时Proposer1会自发的暂停一段时间。 从而让Proposer2成为事实上的Leader,此时Proposer2又可以高效快速的主导一些列值的商定。