设计数据密集型应用 - 分布式系统设计中涉及的问题和普遍解决方案以及研究方向

在分布式系统中,很多事件很容易发生错误(由于网络延迟,节点瘫痪等),为了设计一个健壮并可容错的分布式系统(这里的分布式系统指各节点之间无共享内存,信息或其他资源),工业界和学术界对分布式系统中普遍存在的问题进行了研究和剖析,

数据结果一致性 (Linearizability)

导致该问题的原因是大部分节点是异步同步方式, 不同用户看到的结果可能会有不同(由于同步的延时),理论上时间节点1,A用户看到的结果(数据已更新),应该和后续用户读到结果保持一致(应读到最新的结果);

为什么数据结果一致性如此重要?

  • 在分布式系统中锁的获取主节点投票选取都需通过数据一致性来确保,锁的获取结果只能有一个节点,并且这个结果需要同步到所有其他节点, 确保所有节点结果保持一致;
  • 在另一个场景中,如订票或有限制性条件的分布式事务处理系统中,有限资源(如座位的锁定,商品的限购)都是需要确保多节点数据结果保持一致;
  • 多通道系统数据的一致性,如图片等富媒体信息的传送,并无法做到实时,有可能导致数据的更新不一致;

在分布式系统中,如何做到数据一致性(Linearizability)?

这里我们简单对分布系统的不同模式讨论其对数据一致性的可能性,

  • 单主节点分布式系统,大部分单节点分布式系统是默认数据一致性的,因为写为主节点,读为实时同步从节点,但在主节点不可触达时,会存在数据一致性无法确保的现象;
  • 统计算法下的分布式系统(后面部分介绍),可确保数据一致性;
  • 多主节点分布式系统模式,无法确保数据一致性;
  • 无主节点分布式系统模式,无法确保数据一致性;

但由于网络延迟的不确定性(即没有延时预期 - unbound), 很多实际的分布式系统没有严格遵循严谨的数据一直性,而是选择追求更多的性能优化,放低了对数据一致性的要求;

数据一致性也可以通过total-order操作来确保, 即所有的事务处理都能比较谁发生在谁前面;


有序操作的重要性 (Ordering and Causality)

但让分布式系统跟踪所有操作的顺序有点不太现实, 为了确保部分因果操作(Casual Order)的执行顺序, 有些系统(单主节点分布式系统)通过序列值或时间戳来确保操作的有序性;

对于多主节点分布式系统, 可以通过一下的方式来确定各个事物操作的执行循序:

  1. 对各个主节点操作时间点,去模操作,小的在前,并同步所有其他主节点;
  2. 预先分配序列值给各个主节点,然后同步对应的指令;
  3. 通过Lamport timestamp 算法来确定执行顺序,具体方案是,每个节点有唯一编码和已经执行的指令的counter, 在计算序列号时通过f(counter, node-identity) 来确认, 并且每个节点都记录当前所有节点最大counter, 并更新自身的counter 同步为网络中最大counter;

即使节点间的指令执行是有序的,如用户名唯一,座位票唯一等限制性事务操作也无法在分布系统中得到保证,需要分布式系统中各个节点进行有效的通信, 即有序事务广播 (Total Order Broadcast);

而有序事务的广播和分布式中节点投票算法(Census Algorithm)的问题本质上是一致的,我们将直接进入分布式投票算法问题描述和方案讨论;

分布式投票算法 (Census Algorithm)

主要的应用场景包括,主节点的选择,和涉及多节点事务操作的确认(commit);

为何分布式投票算法(Census Algorithm)会成为分布系统里的难题,大部分原因是在异步分布式系统中,即我们不知道节点是否延迟或瘫痪(可能导致无尽的等待 - wait), 我们如果没有设置时钟或者超时,可能导致系统的死锁;

当下的分布式系统普遍的解决方案是通过双状态确认(Two-Phase Commit), 具体方式是,

1) 主节点发送准备请求到各个分节点,确认待处理事物是否冲突和对从节点资源的锁定,确保后续事务的执行,各节点反馈是否ok

2) 如果主节点接受到各从节点ok的反馈,主节点先对事务进行日志备份,然后发送执行操作给各个节点, 并确保各个节点完成操作,不然锁住主节点的处理进程;如果在准备阶段,任何从节点返回no ok, 则这节点发送放弃执行事务信息给各个节点;

该模式下涉及到两个问题,第一个是主节点瘫痪,a) 在准备阶段瘫痪,则事物处理放弃,因为尚未记录在log中,无法恢复 b) 在执行节点瘫痪,从节点一直等待主节点恢复,并恢复执行事务;

另一个问题是从节点瘫痪, a) 在准备阶段瘫痪,则主节点在超时后,放弃事务执行;b) 在执行阶段瘫痪,主节点一直重试发送执行事务,直到成功;

容错系统投票算法(Fault-Tolerant Consensus)设计

在所有的投票算法中,需要确保一下几点:

  1. 统一协议(Uniform Agreement), 结论所有节点保持一致
  2. 完整性 (Integrity), 所有节点投一次票
  3. 正确性 (Validity), 结果是别的节点建议的
  4. 完结性 (Termination), 没有瘫痪的节点最后决定的结论值

你可能感兴趣的:(架构设计)