分布式算法笔记

选举

Bully算法

选取存活的节点中id最大的做为主节点。MongoDB就是用的这种算法。 缺点:当故障节点恢复后重新加入集群,会导致切换主节点,可能引起频繁切主。

Raft算法

有3种类型的节点: Leader, Candidate and Follower.

k8s内部使用的etcd组件内部,就是用的Raft算法,还有RabbitMQ, TiDB.

缺点:发送消息多

ZAB算法

ZAB 选举算法的核心是“少数服从多数,ID 大的节点优先成为主”.

缺点:由于要对比节点id和数据id, 选举时间长。发送消息多,可能导致广播风暴。

共识

POW(proof of work)

所有节点中,谁的计算能力强,谁就获得记账权。获得之后就广播给其他节点,其他节点接受。

POS(proof of stake)

谁拥有的货币多时间长,谁就拥有记账权。

DPOS(Delegate proof of stake)

某些节点委托别的节点去竞争记账权。

事务

基于XA(xtented architect)协议的刚性事务

一般是数据库要支持XA协议,才能实现2PC, 3PC方法。

二阶段提交

通过一个事务协调器,先发送请求给不同模块做出修改,等收到所有模块都Ok的消息之后,再发送提交事务消息给各模块。

问题:

三阶段提交

分为准备阶段,预提交阶段和提交阶段。

某个地方超时,就会取消

问题:

柔性事务

TCC

Try confirm cancel, 在业务系统实现。

所有业务系统都需要实现这个接口的3个方法,需要实现幂等, 超时重试。

SAGA

核心思想:各个本地事务各自完成,如果其中一个失败,通过事件或者命令的方式让其他的模块执行补偿操作(如果需要)。需要有超时重试机制以及幂等的实现。

本地消息表

MQ最终一致性

这种方案无需本地消息表。目前貌似都是用的RocketMQ. 它支持half message, 只有producer ack了才能被消费者消费该消息。如果该消息一直处于half message状态,则RocketMQ会自动重试,回查该消息,所以消息发送者需要实现消息回查的功能。

或消费端失败,则处理跟本地消息表的处理方法一致。

它跟本地消息不同的是,利用RocketMQ内部实现了本地消息表的功能,缺点是要实现事务回查的功能。

zookeeper实现

有4种节点

临时节点:客户端可以建立一个临时节点,在会话结束或者会话超时后,ZK 会自动删除该节点。 事件监听:在读取数据时,我们可以同时对节点设置事件监听,当节点数据或结构变化时,ZK 会通知客户端。

curator-recipes封装了很多ZooKeeper的常用功能,可以直接调用来实现分布式锁。

排他锁

所有的客户端试图通过调用 create() 接口,在 /exclusive_lock 节点下创建临时子节点 /exclusive_lock/lock,最终只有一个客户端能创建成功,那么此客户端就获得了分布式锁。同时,所有没有获取到锁的客户端可以在 /exclusive_lock 节点上注册一个子节点变更的 watcher 监听事件,以便重新争取获得锁

共享锁

1、客户端调用 create 方法创建类似定义锁方式的临时顺序节点。 2、客户端调用 getChildren 接口来获取所有已创建的子节点列表。 3、判断是否获得锁,对于读请求如果所有比自己小的子节点都是读请求或者没有比自己序号小的子节点,表明已经成功获取共享锁,同时开始执行度逻辑。对于写请求,如果自己不是序号最小的子节点,那么就进入等待。 4、如果没有获取到共享锁,读请求向比自己序号小的最后一个写请求节点注册 watcher 监听,写请求向比自己序号小的最后一个节点注册watcher 监听。