这是我参与「第五届青训营 」伴学笔记创作活动的第19天。是青训营第三阶段课程的最后一次,主要讲了分布式的一些理论,下面对课程内容做一下整理。
理论基础
CAP理论:
- C(Consistence):一致性,指数据在多个副本之间能够保持一致的特性;
- A(Availability):可用性,指系统提供的服务必须一直处于可用的状态,每次请求都能获取到非错的相应(不一定是最新的数据);
- P(Network partitioning):分区容错性,分布式系统在遇到任何网络分区故障的时候,仍然能够对外提供满足一致性和可用性的服务。 同时满足CAP三个特性的系统理论上很难实现,一般都会根据需求对其中一个特性进行取舍。
- CA:强调一致性和可用性,传统的单机系统不用考虑网络分区;
- AP:放弃强一致性,追求分区容错性和可用性,为了保证用户体验,大多数互联网应用比如搜索引擎或流媒体平台等都选择这种方案;
- CP:放弃可用性,一般都是与资产相关的系统采用这种方案。 ACID理论:
- A(Atomicity):原子性,指事务包含的所有操作要么全部执行,要么全部不执行
- C(Consistency):一致性,指事务必须使数据库从一个一致性状态转换到另一个一致性状态
- I(Isolation):隔离性,指多个用户并发访问数据库时,并发事务之间要相互隔离
- D(Durability):持久性,指一个事务一旦被提交了,结果就不会消失,即使宕机也能恢复到提交后的状态 BASE理论:
- Basically Available(基本可用):如果系统出现了不可预知的故障,但还是能用,可能会有响应时间或功能上的损失
- Soft state(软状态):允许数据中存在中间状态,该状态不影响系统的整体可用性,既允许不同节点的数据副本存在数据延时
- Eventually consistent(最终一致性):能保证没有其他新的更新操作的情况下,数据最终一定能够达到一致的状态 该理论是CAP理论的一种延申,对CAP中一致性和可用性权衡的结果。
分布式事务
两阶段提交
引入三个假设:
- 协调者(Coordinator)和参与者(Participants),互相进行网络通信
- 所有节点都采用预写式日志,且日志被写入后即被保持在可靠的存储设备上
- 所有节点不会被永久性破坏,损坏后可恢复 提交请求阶段(投票):
- 协调者向所有参与者发送prepare请求,询问事务时候可以准备提交
- 参与者向协调者返回是否可执行事务 提交阶段(执行):
如果所有参与者都返回yes,说明可提交;
- 协调者向所有参与者发送commit请求;
- 参与者收到commit请求,提交事务并释放占用的事务资源,向协调者返回ack;
- 协调者收到所有参与者的ack,完成事务提交; 如果有参与者返回no或超时未返回(可能宕机),说明事务中断,需要回滚;
- 协调者向所有参与者发送rollback请求;
- 参与者收到rollback请求后,根据undo日志回滚到事务执行前的状态,返回ack;
- 协调者收到所有参与者的ack消息,回滚完成; 一些故障情况:
- 如果协调者宕机,则起新的协调者,带查询状态后,重复二阶段提交;
- 若都宕机则需要人为介入。 需要注意的问题:
- 性能问题,网络通信开销与资源锁定
- 协调者单点故障,需要新起协调者,否则参与者处于中间态无法无法完成事务
- 网络分区带来的数据不一致,如执行阶段发生网路分区,有一部分参与者没有接收到commit消息,会造成数据不一致
三阶段提交
将两阶段提交的请求阶段分为两部分CanCommit和PreCommit
- 协调者询问参与者是否可执行(CanCommit),参与者返回yes或no
- 若全部yes进入PreCommit阶段,协调者发送PreCommit,参与者预执行事务,并将undo和redo信息记录到事务日志中,执行成功后向协调者发送ack
- 若有一个参与者发送no相应,协调者则发送abort请求中断事务否则发送DoCommit请求
- 参与者收到doCommit后进行事务提交,并在完成后释放所有资源向协调者发送ACK
- 协调者收到全部ack后完成事务,否则发送abort,参与者利用undo信息回滚事务
相比于两阶段提交,引入了参与者的超时机制,如果无法即使收到协调者的相应就默认执行commit,从而解决了单点故障问题,并减少了阻塞,但这样也无法保证一致性。
MVCC
一种并发控制方法,维持一个数据的多个版本使读写操作没有冲突,既不阻塞写,也不阻塞读,为每个修改保存一个版本,与事务时间戳相关联,提高并发性能,解决脏读问题。
共识算法
分布式系统中需要一些共识算法来保证一致性,著名的有Paxos和Raft。下面简单介绍一下Quorum NWR模型。 -N:分布式存储系统的节点 -W:一次成功的更新操作要求至少有w份数据写入成功 -R:一次成功的读取操作至少要读R份数据 为保证强一致性的一个必要条件是 W+R>N。若进满足该条件的话,当允许数据被覆盖时会引发并发更新问题,导致数据不一致。