后端 分布式理论-2 day11 | 青训营笔记

109 阅读6分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 11 天

今日笔记内容: 分布式理论-现代架构基石, 第二段

分布式事务

两阶段提交 (Two-phase Commit)

Prepare(写入) + Commit(提交)

假设:

  1. 引入协调者(Coordinator)和参与者(Participants)
  2. 所有节点都采用预写使日志, 且日志被写入后可以持久化在可靠的存储设备上
  3. 所有节点不会永久性损坏, 损坏后仍然可以恢复 问题:
  4. 性能问题: 需要多次节点间相互通信, 耗时过大, 资源需要被锁定
  5. 协调者单点故障: 如果事务协调者节点宕机, 需要另起新的协调者, 否则参与者陷入中间状态, 事务无法正常结束
  6. 网络分区带来数据不一致: 部分参与者收到Commit消息, 另一部分没有

三阶段提交

将两阶段提交中的Prepare阶段, 拆成两部分: CanCommit和PreCommit, 避免了commit时资源不足导致commit失败或阻塞的问题

关于分布式事务更详细的知乎文章: (分布式事务有这一篇就够了! - 知乎 (zhihu.com))

MVCC

多版本并发控制, 维持一个数据的多个版本使读写操作没有冲突, 不阻塞读写, 提升并发性能

版本通过时间戳区分

Spanner : 使用TrueTime API 提供物理时钟, 偏差在1~7ms之间

时间戳预言机(TSO), 利用中心化的授时方式, 所有协调者向中心化节点获取时钟

乐观锁与悲观锁

乐观锁: 不主动加锁, 更新数据时先判断是否已经有线程更新 悲观锁: 操作数据前先把数据锁住, 操作完成后解锁

共识协议

Quorum NWR模型

Quorum 法定人数

  • N: 有多少节点
  • W: 一次成功的更新操作需要至少w份数据
  • R: 一次成功的读数据需要从R份拷贝中读取

为了保证强一致性, 要满足W+R>N

用户可以调整W,R来选择CAP特性

Raft 协议

基于Leader/Follower机制的共识协议, 客户端与Leader通信写入数据, Leader负责向Follower同步数据

  • Log(日志), 节点之间存储的信息, 只允许追加写, 避免数据被覆盖的问题
  • Term(任期号), 单调递增, 每个任期内最多有一个Leader
  • Committed: 日志被复制到多数派后, 才可以被认为可以提交
  • Applied: Leader Commited日志后, 将日志内容应用到状态机上

两大RPC:

  • 选举
    • 超时(随机时间)没有收到Leader心跳包, 则开启新任期, 尝试竞选, 向其他节点发送投票请求
    • 收到多数派响应, 成为新任期Leader
    • 响应没有达到多数派, 继续下一轮选举
    • 收到其他投票请求, 比较任期号, 选择投票给自己还是其他节点
    • 每个节点一个任期内只能投一次票
  • 日志复制
    • Leader收到客户端新日志后, 将日志复制到其他Follower上
    • Leader保留所有Follower当前日志下标, 如果不同步则定时发送复制RPC
    • 新日志成功复制到多数派节点后, 更新提交下标, 并通知其他Follower
    • 其他Follower接收到提交下标后, 更新自己的状态机

Paxos

比Raft协议更早提出, 但更加复杂

  1. Multi-Paxos 可以并发修改日志, 而Raft的日志必须是连续的
  2. Multi-Paxos 可以随机选主, 不要求最新最全的节点当选Leader
  • 优势: 所有节点都可以写入, 且不要求连续写, 因此性能更高
  • 劣势: 不保证有节点保存所有状态, 恢复流程复杂, 需要同步历史记录

思考题

  1. 分布式系统有那些优势和挑战?
    分布式的优势在于他可以理论上无限水平扩容, 也可以通过冗余机制来容灾. 挑战在于大规模分布式系统基础设施的不可靠性, 如何在集群间形成共识和有效的通信.
  2. 两将军问题为什么理论上永远达不成共识?
    每次重复通信只能增加消息可信的概率, 不能达到100%的可信
  3. 为什么TCP采用三次握手? 而不是两次和四次?
    三次握手验证了双端的发送(seq),接收响应能力(ack)
  4. 为什么在4将军问题中, 增加一轮协商就可以对抗拜占庭故障?
    通过可信信息的冗余来覆盖不可信信息
  5. 什么是最终一致性? 什么是线性一致性?
    最终一致性: 写入过程中, 不保证所有节点读取数据的一致性, 只保证在有限时间内, 能将数据更新到所有节点上 线性一致性: 写入过程中, 如果有节点读取到新数据, 则强制同步到所有其他老节点上, 保证在读取到新数据后, 不会再读取到老数据
  6. CAP理论中, 请举例说明可用性和一致性的矛盾?
    在AP场景下, 网络产生分区, 且系统仍然提供服务, 则不同分区的服务无法满足一致性 在CP场景下, 网络产生分区, 必须停止服务, 避免后续对系统状态的更新, 保证系统的一致性
  7. ACID理论中的一致性和CAP理论中的一致性有什么区别?
    CAP理论中的C注重多节点之间同一份数据的一致性, ACID中的C关注的是整体数据逻辑上的一致性
  8. 两阶段提交中, 什么场景需要数据库管理员介入?
    两阶段提交中可能会出现预写入死锁, 或提交时机器宕机导致数据不一致, 此时需要管理员介入
  9. 三阶段提交缓和了两阶段提交的哪两个问题?
    1. 单点故障,
    2. 阻塞问题
  10. 什么场景适合乐观锁? 什么场景适合悲观锁?
    乐观锁使用与数据竞争较小的场景, 通常是读频繁, 避免反复加锁. 悲观锁适用于更新频繁的场景, 需要互斥保证更新的安全性
  11. 在共识协议中, 为什么说允许数据被覆盖会带来数据一致性问题
    同一份数据被更新后没有同步到所有节点上, 可能读取到老的数据
  12. RAFT协议中, Leader写成功日志Log20但未同步给Followers后发生宕机, Follower重新选举后产生一条新的日志Log20, 这时Leader重启, 整个系统发现两种不一样的Log20记录, 如何区分并拒绝掉前面的Log20?
    Follower重新产生了一条新日志Log20, 此时Follower已经成为新Leader, 并尝试将新Log20记录同步给其他节点, 老Leader接收到新Leader的日志同步请求后, 降级为Follower, 并将自己原来的Log20更新为新的.
  13. RAFT协议中, Stale读是如何产生的? 该如何解决Stale读的问题 旧Leader在响应没有同步的日志, 1. 只响应已提交的日志, 2. Leader重启后必须经过心跳包后才响应客户端, 可以通过心跳包判断是否有新Leader产生.