分布式&一致性算法

名词介绍

CAP

CAP:3选2,不能3者兼得

  • 一致性(Consistency):(多个节点的)数据必须一致

  • 可用性(Availability):集群的并发量

  • 分区容错性(Partition tolerance):把同一个数据保存在不同的集群,以保证某个节点下线,还能从集群 拿到数据。分区:集群中不连通的多个部分(比如某个节点断网了)

  • CP:损失A,数据同步时,禁止访问这个数据。所有节点同步完 再开放对该数据的访问。

  • AP:损失C,不是完全一致的。任何时候都可以访问。数据同步时,不需要所住数据

BASE

BASE:CAP理论中一致性和可用性权衡的结果,保证P的时候,CA略有不足,但可以接受

  • Basically Available(基本可用)
  • Soft state(软状态)
  • Eventually consistent(最终一致性)

分布式事务

参考:https://blog.csdn.net/qq_31960623/article/details/116429261

2PC

  1. 准备阶段:(获取锁并)在本地执行事务,准备提交(提交),返回执行状态
  2. 提交阶段:都完成就提交,有没完成的就回滚

3PC

  1. CanCommit:参与者并不真实获取锁占用资源,只是对自身执行事务状态的检查,查看是否具备执行事务的条件,进而回复询问。
  2. PreCommit:执行事务,准备提交,类似2PC的2阶段
  3. do Commit:都完成就提交,有没完成的就回滚

全局时钟

  • TrueTime物理时钟
  • HLC逻辑时钟(分布式授时)
  • TSO中心化授时
  • Lamport

Raft

参考
https://blog.csdn.net/weixin_44627989/article/details/107141274
https://blog.csdn.net/qq_45993646/article/details/122663476
https://blog.csdn.net/MEIYOUDAO_JIUSHIDAO/article/details/123431849

使用案例:Kafka, zookeeper, Nacos(CP), etcd, K8s, RocketMQ, Curve

实现:Hashicorp RaftRatis(Apache), SOFARaft(蚂蚁金服)

讨论范围

讨论某topic/某partition的集群

里面的节点数=备份数

节点状态

每个节点有以下状态,主要为leader follower,选举时的状态candidate

  • Leader:主酒店,只有一个
  • Follower:集群的follower,选举时参与投票
  • Candidate:各个节点竞争Leader的状态(进行选举)。

当follower迟迟没有收到leader的心跳(时间超过election timeout)leader掉线,follower会转换为该状态,竞争leader。

节点信息

  1. 节点id
  2. 节点类型:主要状态leader follower,临时状态candidate
  3. 所在任期(term):leader故障时+1
  4. 日志组(Logs):同时leader 为每一个 Follower 维护一个 nextIndex,表示当前同步的索引
  5. 选举超时(election timeout):心跳超时时间,看candidate介绍,Raft中是随机生成的(所以也叫randomized election timeouts
  1. leader定时向follower [发送心跳 ,同步Logs];超过半数节点收到了log,则设置commit为当前index
  2. followerelection timeout时间内未收到leader的心跳,则进入candidate状态,竞争leader。

日志复制(Log Replication)

每个节点又有记录,有以下内容

  • index:索引。连续的,递增的,1,2,3,4,...
  • term:所在任期。非严格递增的,可以不连续的,1,1,1,3,3,3
  • entry:日志条目(内容)。这与实际业务相关

日志复制流程

  1. leader将日志加到自己的日志的最后(append),但未提交。()
  2. leader向follower发送日志记录(放在心跳请求里),
  3. follow新增之前进行一致性检查失败。(未通过,则减小nextIndex,一直未通过,一直减小;一般发生在leader刚选举出来时)

leaderfollower,对于某一个index,term相同,则认为 index<=当前index 的log都相同
一致性检查失败:对于 之前的日志 是否相同

选举(leader election)

follower转换为candidate时进行选举,以下为操作流程

  1. term++
  2. 投一票(只能投一票;最开始投自己;只投log index>=自己的;当新的投票请求比自己的大时)
  3. 向其他节点发起投票RequestVote RPCs(希望他们投自己一票)
  4. 某节点收到majority voting(超过半数的票),则转化为leader,其他为followerleader会将nextindex设置成和自己一样
  5. 投票结束 也没有majority voting,重新投票

leader租约

定时重新申请成为leader,一般都会成功(只有自己发起 && log index肯定为最新),(变化只有term++

故障恢复

  1. leader有自己的term(任期),
  2. 新leader的term = leader的term+1
  3. follower只认term最大的follower;
  4. 当老leader恢复时,发现 集群的term比自己的大,自动转化为follower,防止脑裂

Paxos

https://zhuanlan.zhihu.com/p/31780743
https://zhuanlan.zhihu.com/p/361108372

分布式&一致性算法_第1张图片

  1. 生成n:作为Proposal ID;全局唯一且递增(可用 时间戳+ServerID)
  2. 阶段1/Prepare:Proposer-[Prepare:{n:ProposalID}]->Accepter
  3. 阶段1/Promise:
    • 若接受:Accepter-[Promise:{acceptedProposal,及其Value}]->Proposer
  4. 等待多数返回
  5. 阶段2/Propose:Proposer-[Prpose:{n:ProposalID,value:max(Value)}]->Accepter
  6. 阶段2/Accept:
    • 若接受:Accepter-[Accept]->Proposer
  7. 等待多数返回
  8. 阶段3:Proposer-[Leanrn]->Learner

ZAB

Zookeeper Atomic Broadcast
使用案例:Zookeeper

  1. 写请求全部发送到Leader
  2. 写请求有序执行,
  3. 多数节点Follower 响应 ack,则提交

优化

  1. 写请求 批量发送
  2. 异步获得 Follower 的ack

ZAB中有Oberserver:观察者,选举时不参与投票,与ZAB没有关系

Gossip

使用案例:Apache Cassandra,Redis(Cluster模式),Consul

消息类型

  • Anti-Entropy(反熵):以固定的概率传播所有的数据
  • Rumor-Mongering(谣言传播):仅传播新到达的数据

通信方式

  • Push: 节点 A 将数据 (key,value,version) 及对应的版本号推送给 B 节点,B 节点更新 A 中比自己新的数据
  • Pull:A 仅将数据 key, version 推送给 B,B 将本地比 A 新的数据(Key, value, version)推送给 A,A 更新本地
  • Push/Pull:与 Pull 类似,只是多了一步,A 再将本地比 B 新的数据推送给 B,B 则更新本地

PBFT

一致性hash

https://zhuanlan.zhihu.com/p/73720447

  1. 有个hash环,hash值在 [0,232-1]
  2. 有很多物理节点node
  3. 每个物理节点对应多个虚拟节点dev
  4. 虚拟节点尽量分散在hash环上
  5. 每个hash会把值存在 该hash前的最近的dev

有dev调整(增删)时,方便数据的调整;只需要求修改相关的存储,不需要 重新hash
每个node有多个dev 是为了 避免数据倾斜

Quorum NWR

https://zhuanlan.zhihu.com/p/46551227

  • 保证 R+W>N,即能读到正确的数据。
  • N 为副本的数目,
  • W 是写成功需要写的份数,
  • R 为读成功需要读的份数,
  1. 假设R为5
  2. W为2,那么现在有2个副本为最新值,3个副本可能为原来的值
  3. 假设一个最倒霉的场景
    • 后面提到的3个副本碰巧为原来的值
    • 读取的时候先读那3个副本,再读一个才读到最新值
    • 这是R为4
    • 刚好满足 4+2>5

你可能感兴趣的:(分布式)