CAP 理论理解
1:问题与理论
1.1 问题
分布式环境下多个计算节点,节点间通过网络连接,节点间共享状态(数据,不一定是相同数据,可以是整体业务数据的不同部分),当状态更改后,客户端读取时如何保证读取到最新的数据。即在分布式计算环境下,节点间状态同步问题。
对这个问题的经典描述就是 CAP 理论。
CAP 是对分布式一致性解决方案特点的一种观察角度,归纳的出的一种规律。
1.2 CAP 理论
1.2.1 定义
加州大学的计算机科学家 Eric Brewer 提出,分布式系统有三个指标
C:(Consistency)、A(Availability)、P(Partition)不能同时满足。
1.2.2 具体含义
C:一致性
客户端进行状态修改操作成功后,其他客户端读取时要能读取到最新修改的数据。
A:可用性
非故障节点在指定时间内返回合理响应(不能是错误或超时)
-不要求最新数据
P:分区容错性
有节点发生故障或与其他节点无法通信是,系统仍然可以正常提供服务。
--不要求兼容多少故障节点,至少兼容一个节点故障。
1.3 为什么不能全部满足
1.3.1 分布式下要保住 P
分布式计算下,用多个节点计算,大部分场景下要兼容某个节点故障。
需要满足 P,某种程度上如果放弃 P,意味着有节点故障系统就不提供正常提供服务,也就处于不可用状态了。因此主要在 CA 间进行平衡,也就是 CP,AP 或更侧重 C,还是更侧重 A。
1.3.2 矛盾的 C 与 A
共享状态下,修改状态时,必然要进行节点间的状态同步,同步时网络可能故障导致同步失败,
如果满足一致性(CP),就取消这次操作,如果要满足可用性(AP),就会导致用户读取到同步失败节点时出现不一致。
1.4 要点注意
CAP 关注的粒度是数据,而不是整个系统(一个系统中不同类型数据数据可有不同的策略)。
系统在没有分区错误的情况下要同时满足 AP。
忽略正常情况下的网络延时(多个节点间拷贝确认等必然存在短暂的网络延时)
2:实践方案
大部分场景下不是完全放弃 A 或 C,只是侧重不同。
出现分区故障时不同的场景要满足不同侧重点,也就出现相应的方案
2.1 CP 型
在一致性比较重要的场景下,选择 CP 型,代价是在可用性或性能上都有些妥协。
分布式事务方案型(专制型-全部同意或主节点同意-主节点内部可拷贝多份保证状态不丢失)
分布式事务:操作数据位于多个数据库,要求一致性。
比如两阶段提交:将数据更改为资源锁定与提交,如果有一个提交失败其它回滚。同时牺牲了可用性与性能。接收请求的节点根据各个事务的反馈决定是否成功。
主从模式:单个主节点,主节点收到请求后同步给从节点,如果要求从节点必须同步成功算成功,就是 CP 模式。主节点的可用性可通过监控或内部选主多种方式在主节点故障时切换主节点。会出现短暂的写不可用。redis 主从+sentinel(哨兵),zookeeper 也属于主从模式。写只到主节点进行,主节点故障切换或重新选主,读从节点(C 是否妥协,看写成功的条件是否要求从节点全部成功),主节点的决策是根据从节点投票来的。
客户端只读主节点还是也读从节点:只读主节点,写成功后,读到最新的。主从同步是否同步成功再反馈客户度写成功(决定是否会出现写丢失问题)
数据多写(民主型-多数同意):写入多个节点,大部分成功才算成功。比如同时写入 3 个节点,至少两个成功后才算成功,否则回滚。读的时候也读取多个节点,有冲突时选择高版本的数据,也可以只读主节点(一主多从,多从为了包装单节点故障后仍然可用)。Paxos、ZAB、Raft 这些协议的实现都属于这个类型。cassandra 多写多读。
如果出现分区故障,读的节点时分区故障节点,不能实现读到最新数据。zookeeper 实现的是顺序一致性,后续读其他节点可以保证顺序一致性。
专制分散型
为了减少故障节点的影响,可以在选择 CP 模型时,将写的数据根据规则分区,即便出现节点故障,大部分数据仍然可以正常使用,只有归属故障节点负责的数据才短时间不可用。HBASE 就是这种模式,多个 RegionServer 负责不同数据,节点故障时,只影响这个 server 的,HMaster 记录 key 与 HRegionServer 的映射。不同节点负责不同数据的写结果裁决
,主节点仍然要内部拷贝多份,只是由不同的主节点负责。redis 集群的 cluster 模式。
redis 的 cluster 也要给主节点配置从节点,否则故障后导致不能使用,同时 redis 的主从不保证数据不丢失(主节点写成功就反馈成功,异步同步到从节点,这个过程可能丢失写的数据,也可以配置成写到主节点时同步的同步到从节点--不过性能不高,redis 目的是高性能)
异步成功(成功延迟):
写时返回,但并不告知成功,只告知在处理中,延后告知是否成功。在一些高并发系统进行异步处理时最常采用的模式。银行转帐告知处理中,成功后再告知成功。是强一致性,但是把回应成功|失败的时间拉长来实现的。
2.2 AP 型:
可用性要求高的场景,放宽一致性的强度,允许短期不一致 。出现分区故障时,先满足可用性,后续通过异步或各种补偿措施,实现一致性。
DNS,红包抢与支付
单主多从模式,延期一致:
在一个主节点更新,后续同步到其他从节点,同步成功前,其他节点读到的是过时的数据,但最终会读到新数据。比如 DNS。
多个主节点都可写入,冲突后续解决
实现的是最终一致性,后续冲突解决方案有
后台合并
多个写节点,冲突时后台按某种规则(时间戳等)进行选择合并。
比特币理论上也是多写,然后内部合并-谁先谁成功。然后全部抉择,实现了强一致性--只是在性能上做了大量的让步。
用户侧合并
多个写节点,冲突时后台保存多个,用户侧进行按场景选择合并策略
先成功,失败后再补偿-失败补偿:
更新后反馈成功,后续更新其他节点失败,补偿,或撤销。
比如抢红包,高并发下先抢成功,但转账时账户异常转账失败,在提示收款人失败,同时将钱退给发红包的人。
2.3 其它
分区故障恢复
恢复后要通过状态复制,冲突解决将故障节点或冲突的数据恢复到正常状态。
很多场景 CA 间是侧重并不是完全满足
zookeeper:多被认为是 CP 型的,当主节点故障时,不提供服务,重新选取出主节点后再提供服务。但 C 也是做了妥协的,写时超过半数成功返回,读从节点存在读时,可能读到过时数据。如果做 WATCH,可以观察到最新数据,只能说更侧重 C。
参考上篇
评论