上一篇(L12)

下一篇(L14)

一致性:侧重于是内部的观测结果,要求节点间数据百分百一致;

共识:侧重于是外部的观测结果,要求客户端请求任意节点获取的数据需要一致,即在集群的所有节点需要对一个提案达成共识,且节点运行故障,保证所有参与节点最终都同意同一个值;

事务:

两阶段锁(2PL); 两阶段提交(2PC);

目标问题:跨机器的原子操作;

关键方法:begin、commit、abort; 关键属性:ACID;

可串行化和可线性化: 后者更严格,时间&实际顺序要匹配,整体顺序不能改变; 而前者仅要求在并发环境下,按顺序执行,可能重排,即同一时间执行一个事务;

隔离事务:并发控制: 悲观并发控制(先许可后操作):使用锁维护可串行化; 乐观并发控制(先操作后许可):提交时检查是否符合线性化,失败则直接返回或者重试;

2pc

  • 属于一致性算法;
  • 主要用于分布式事务的场景;
  • 是强一致性,中心化的原子提交协议;
  • 两个阶段:准备阶段、提交阶段;
  • 两个状态:协调者,参与者;

协调者:负责整个事务中的提交、回滚操作;

参与者:拥有事务需要操作的资源;

站在应用程序的视角下:

  当应用程序启动一个分布式事务时,他首先向协调者请求全局唯一的事务id;

  应用程序在每个参与的节点上执行单点任务,并将全局唯一的事物id添加到事务上,此时的读写都在单节点上完成,如果出现问题,则协调者和其他参与者都可以安全终止该事务;

  当应用程序准备提交时,协调者会向所有参与者发送准备请求,并附带事务id,如果有任何一个参与者没有响应或者失败,则协调者会通知所有参与者放弃事务;

  参与者收到准备请求后,确定可提交事务后响应ok

  协调者收到所有准备请求的答复后,将决定(提交还是回滚)写入磁盘的事务日志中,之后协调者将提交请求发送给所有参与者,如果出现失败或者超时,协调者都需要一直重试,直到成功为止,决定提交后不可回滚改变

从协调者视角下: 第一个阶段:Perpare阶段

  协调者向参与者发起perpare请求(携带本次事务所需要的操作与对应资源),当参与者收到操作后,在本地记录事务日志(redo&undo),并且锁定对应资源,如果参与者认为自己可以提交事务的操作,则响应yes给协调者,反之响应no;

第二个阶段:Commit阶段

  存在两种可能:提交或者回滚;如果所有参与者都响应yes,则协调者执行提交操作,即向参与者广播提交命令,参与者根据事务日志,执行完成后返回ack,最后协调者收到所有ack后响应客户端 成功; 如果有任一参与者响应no,或者没有返回ack,协调者将执行回滚操作,即广播回滚命令,如果参与者已经执行了事务,则利用事务日志的undo,回滚操作,当回滚完成后,依然需要返回ack给协调者,当协调者收到全部ack后,响应客户端 失败;

存在的问题:

  如果在准备阶段发生了问题(例如网络延迟、参与方宕机等),事务协调器需要等待一个超时时间才能确定是否中止事务; 存在的问题:

  1. 同步阻塞,因为prepare会锁定对应的资源,导致其他事务如果同样请求这个资源时,会阻塞等待;
  2. 协调器宕机(单点故障)
    • 此时正在参与的所有事务参与者将会被阻塞,因为它们无法得知全局事务的最终状态;
    • 事务一直处于未完成状态: 在第一阶段中,事务协调器向所有参与者发送准备请求,并等待它们的响应。如果事务协调器宕机,某些参与者可能已经完成了第一阶段的操作,但还未收到提交或中止的指令。这些事务可能会被悬挂,直到协调器恢复或者其他机制介入;
    • 不一致的状态: 在两阶段提交中,为了确保所有参与者在最终决策(提交或中止)之前都同意事务,事务协调器必须协调所有参与者的操作。如果协调器宕机(如果没宕机(或者说协调器也有先记日志),但向节点发送commit时失败,同样导致数据不一致),可能会导致某些参与者已经提交了事务,而其他参与者却尚未收到提交指令,无法确定是否应该提交还是回滚事务,这可能导致系统处于不一致的状态;
    • 事务丢失: 如果事务协调器宕机并且不可恢复,那么整个事务可能会丢失。

  可以采取一些措施,例如使用备份事务协调器、实现故障转移机制、定期持久化事务状态等;

raft提供高可用性,所有节点做同样的事(all servers go the same)

2pc是跨服务器的原子操作,所有服务器操作不同的事(all server opereate on different data);