名词介绍
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
- 准备阶段:(获取锁并)在本地执行事务,准备提交(提交),返回执行状态
- 提交阶段:都完成就提交,有没完成的就回滚
3PC
- CanCommit:参与者并不真实获取锁占用资源,只是对自身执行事务状态的检查,查看是否具备执行事务的条件,进而回复询问。
- PreCommit:执行事务,准备提交,
类似2PC的2阶段
- 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 Raft
,Ratis(Apache)
, SOFARaft(蚂蚁金服)
讨论范围
讨论某topic/某partition
的集群
里面的节点数=备份数
节点状态
每个节点有以下状态,主要为leader
follower
,选举时的状态candidate
- Leader:主酒店,只有一个
- Follower:集群的follower,选举时参与投票
- Candidate:各个节点竞争Leader的状态(进行选举)。
当follower迟迟没有收到
leader
的心跳(时间超过election timeout
)leader掉线,follower会转换为该状态,竞争leader。
节点信息
- 节点id
- 节点类型:主要状态
leader
follower
,临时状态candidate
- 所在任期(term):leader故障时
+1
- 日志组(Logs):同时
leader
为每一个 Follower 维护一个nextIndex
,表示当前同步的索引 - 选举超时(
election timeout
):心跳超时时间,看candidate
介绍,Raft中是随机生成的(所以也叫randomized election timeouts
)
leader
定时向follower
[发送心跳
,同步Logs
];超过半数节点收到了log
,则设置commit为当前indexfollower
在election timeout
时间内未收到leader
的心跳,则进入candidate
状态,竞争leader。
日志复制(Log Replication)
每个节点又有记录,有以下内容
- index:索引。连续的,递增的,
1,2,3,4,...
- term:所在任期。非严格递增的,可以不连续的,
1,1,1,3,3,3
- entry:日志条目(内容)。这与实际业务相关
日志复制流程
leader
将日志加到自己的日志的最后(append),但未提交。()leader
向follower发送日志记录(放在心跳请求里),follow
新增之前进行一致性检查失败
。(未通过,则减小nextIndex
,一直未通过,一直减小;一般发生在leader
刚选举出来时)
leader
与follower
,对于某一个index,term相同,则认为 index<=当前index 的log都相同
一致性检查失败:对于 之前的日志 是否相同
选举(leader election)
follower
转换为candidate
时进行选举,以下为操作流程
- term++
- 投一票(只能投一票;最开始投自己;只投
log index
>=自己的;当新的投票请求比自己的大时) - 向其他节点发起投票
RequestVote RPCs
(希望他们投自己一票) - 某节点收到
majority voting(超过半数的票)
,则转化为leader
,其他为follower
。leader
会将nextindex
设置成和自己一样 - 投票结束 也没有
majority voting
,重新投票
leader租约
定时重新申请成为leader
,一般都会成功(只有自己发起 && log index
肯定为最新),(变化只有term++
)
故障恢复
leader
有自己的term
(任期),- 新leader的term = leader的term
+1
- follower只认
term最大
的follower; - 当老leader恢复时,发现
集群的term比自己的大
,自动转化为follower,防止脑裂
Paxos
https://zhuanlan.zhihu.com/p/31780743
https://zhuanlan.zhihu.com/p/361108372
- 生成n:
作为Proposal ID
;全局唯一且递增(可用 时间戳+ServerID) - 阶段1/Prepare:Proposer-[Prepare:{n:ProposalID}]->Accepter
- 阶段1/Promise:
- 若接受:Accepter-[Promise:{acceptedProposal,及其Value}]->Proposer
- 等待多数返回
- 阶段2/Propose:Proposer-[Prpose:{n:ProposalID,value:max(Value)}]->Accepter
- 阶段2/Accept:
- 若接受:Accepter-[Accept]->Proposer
- 等待多数返回
- 阶段3:Proposer-[Leanrn]->Learner
ZAB
Zookeeper Atomic Broadcast
使用案例:Zookeeper
- 写请求全部发送到Leader
- 写请求有序执行,
- 多数节点Follower 响应 ack,则提交
优化
- 写请求 批量发送
- 异步获得 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
- 有个hash环,hash值在 [0,232-1]
- 有很多物理节点node
- 每个物理节点对应多个虚拟节点dev
- 虚拟节点尽量分散在hash环上
- 每个hash会把值存在 该hash前的最近的dev
有dev调整(增删)时,方便数据的调整;只需要求修改相关的存储,不需要 重新hash
每个node有多个dev 是为了 避免数据倾斜
Quorum NWR
https://zhuanlan.zhihu.com/p/46551227
- 保证 R+W>N,即能读到正确的数据。
- N 为副本的数目,
- W 是写成功需要写的份数,
- R 为读成功需要读的份数,
- 假设R为5
- W为2,那么现在有2个副本为最新值,3个副本可能为原来的值
- 假设一个最倒霉的场景
- 后面提到的3个副本碰巧为原来的值
- 读取的时候先读那3个副本,再读一个才读到最新值
- 这是R为4
- 刚好满足 4+2>5