2PC:两阶段提交协议。
事务分为提交和执行两个阶段。
阶段一:协调者发送事务的请求到事务的执行方,执行方执行事务并记录undo和redo,但不提交事务。然后返回执行情况。
阶段二:协调者发送提交事务请求到各执行方,让各方提交事务或者回滚事务。
存在问题:1)协调者是个单点问题。2)如果第二阶段超时了会导致脏数据。
3PC:两阶段协议的改进。二阶段一来就开始执行执行事务,如果有人不能执行这样会导致占用资源。所以将一阶段拆分为两个阶段。增加先询问对方是否可以执行事务。
阶段一:协调者询问各方能否执行事务。
阶段二:协调者发送事务的请求到事务的执行方,执行方执行事务并记录undo和redo,但不提交事务。然后返回执行情况。
阶段三:协调者发送提交事务请求到各执行方,让各方提交事务或者回滚事务。
存在问题:和上面问题一样,还多了一次执行请求。
TCC协议:上面2阶段,3阶段都是数据库层面的常用协议,tcc是上层应用的协议。
Try尝试阶段:尝试执行。比如先把状态改为一个中间状态。确保别人不会动这个数据。
Confirm确认阶段:确认执行。把这个中间状态改为最终状态。
Cancel取消阶段:取消执行。如果失败了把这个中间状态恢复到原始状态。
zab协议:是分布式协调组件zookeeper采用的分布式一致性协议。他的目的就是要保证数据的一致性。
zab协议要讲清楚可以分为几个部分:
1,协议里有三种成员:
领导者:接收写请求,集群只有一个领导者。所以这也是zookeeper会有写入瓶颈的原因。
跟随者:参与写入请求的投票和选举,并随时准备成为新的领导者。
观察者:只负责只读请求,他的作用是分摊读的压力。
2,怎么选举的?怎么恢复数据?
当跟随者发现和leader断开链接时会发起选举。其中有个最重要的就是投票信息。这个投票信息由:任期编号(谁当选leader,这个任期就+1,可以理解为多少届)+事务编号+节点编号(配置节点时填的那个数字编号)组成。
当节点发现和leader失去联系时,节点会发起选举。节点会拿着投票信息,先投自己一票,然后广播出去叫别人投自己。最后对比自己的选票池,谁的票最多谁就是leader。那么选谁做为leader呢?关键就在于这个投票信息的判断了。
1)判断任期大的优先。
2)任期一样的判断事物id大的优先。
3)事务ID也一样那就选节点编号大的优先。
当别人叫你投票时,你判定别人比你更适合当leader时,你就会把票投给他。否则不与投票。当一个投票周期结束时,你会对比自己的投票池,看你收到了几个票,投出去了几个票,你是否满足票数过半。如果满足就宣布你是leader,并广播出去。别人收到你是leader的广播后,别人也会看他的投票池,并确认你是否为leader。如果都确定了,那么将进行数据同步,将leader的数据同步到跟追者。等数据都同步完成时,leader才能接收写入请求。
2,怎么写数据?
leader写入数据时,会往跟追者也写一份(这时还没真正提交数据)。当过半的跟随者都写入时成功时,leader会让跟随者提交数据,这时跟随者才提交数据。这时一个写入才算完成。类似二阶段写入。所以写入性能不会很高,是单机的。而且这里是一个请求完成才会进行下一个请求,所以也是有顺序的。
3,怎么读数据?
所有节点都可以直接读数据。
4,会不会丢数据呢?
当一个事务被过半的跟随者成功响应ack后,只向其中一个跟随者发送commit信息则或者一个commit都没发出则leader退出了。这种情况,跟随者会将自己没提交的提交了,然后进行选举,有高事务ID的跟随者会当选leader。这个数据不会丢。
当一个事务刚被发出来,比如只有一个跟随者收到了消息后,其他都还还没收到。这时leader退出了,那么这个接收者会提交本事务。这里又分两种情况:这个跟随者自己也挂了,那么其他跟随者选举出来的肯定就没这个数据。这个跟随者没挂,他当选了,这个数据就没丢。就算当这个跟随者恢复了,别人已经当选了。那么他多出的这个数据也会被要求丢掉。