文章目录
数据复制
目的
主从复制
复制形式
复制日志
运维变更
副本一致性
多主复制
适用场景
处理写冲突
无主复制
quorum一致
quorum一致局限
数据分区
分区方式
二级索引
分区再平衡
取模
固定数量分区
动态分区
按节点比例分区
请求路由
事务
分布式系统问题
不可靠网络
不可靠时钟
分类
依赖时钟的风险
不可靠信息
抽象模型
一致性与共识
可线性化
顺序保证
事务与共识
数据复制
目的
高可用。容忍单个副本故障、网络分区。
可扩展。多副本提高读吞吐量。
低延时。距用户较近,交互更快。
主从复制
写:主节点。读:从节点。
到主节点网络问题影响所有写入。
复制形式
同步复制。从节点确认写入后返回。
从节点数据最新版本,可瞬间故障切换。
异步复制。从节点无需确认。
从节点不会影响主节点吞吐量。
半同步复制。一个从节点同步,其余异步。
复制日志
基于语句。INSERT等。
非确定性语句,now等执行结果不同。
依赖现有数据的操作,如UPDATE,需要保证副本按照相同顺序执行。
基于物理日志WAL,如redo。
和存储引擎耦合,偏底层。如果存储格式不前后兼容,无法滚动升级。
基于逻辑日志,如binlog。
复制和存储逻辑解耦。向后兼容,方便异构数据。
包含行前后值。记录因果关系,处理并发。
基于触发器。
灵活但是增加数据库压力。
运维变更
新增从节点。
一致性快照 -> 复制日志追赶变更。
从节点失效。根据复制日志追赶式恢复。
主节点失效。节点切换。
确认主节点失效。如心跳超时。
选新的主节点。选举->共识算法推送,节点和主节点差异小优先。
新主节点生效。写请求转发,原主节点恢复后降级成从节点。
节点切换风险。
脑裂。老主节点上线未失效,写冲突。
数据丢失。异步复制从节点落后,如果外部依赖这部分数据,危险。
使用自增主键,外部映射到该主键关系错误。
频繁切换。超时时间选取,可使用手工切换。
副本一致性
读写一致。从节点读到自己主节点写的数据。
从主节点读取用户可能修改的数据。
读取时带时间戳(版本号或时钟),副本需要覆盖写入的时间戳,否则重选副本。
单调读一致。读到新版本后不再读到旧版本。
根据用户id路由指定副本。
因果一致。先发生先读。
有因果关系的写入从一个副本读。
happens-before追踪因果。
多主复制
适用场景
多数据中心。
性能。就近写,不用跨广域网。
容错。切换数据中心。
数据中心失效。
到数据中心的网络失效。
离线客户端。等价于单节点数据中心+极不可靠的网络。
协作编辑。
处理写冲突
异步检查:主节点各自写入的优势。
同步检查:简单。
避免冲突。用户路由到单节点写,但漫游或网络故障可能重新路由产生冲突。
收敛于一致。
最后写入者获胜(LWW)。
保留写入版本号最大记录。
保留节点版本号最大记录。
合并并发写入,依赖应用层(自动)、用户(手动)解决冲突。
版本号标记操作的因果关系。
无主复制
用户写入多个节点并从多个节点读取。
通过数据版本号确认最新的有效值。
quorum一致
读写quorum。n个节点,w个写入确认,r个读取,w+r>n保证读写节点有重合,可以读到最新值。
读修复。读取到旧版本回写新版本。
反熵。后台进程check更新数据版本。
quorum一致局限
部分成功、复制滞后导致。
读写并发。写操作部分完成,读取不确定。
部分写失效。写操作成功数<w,操作失败但是能读取新值。
宽松quorum条件无法保证读写节点有重合。
网络分区导致可达节点<w个,临时节点暂存数据,保证总共写入w个,网络问题解决后数据回传。
数据分区
目的:提高扩展性,大数据集分散在多个节点上,分担查询负载。
partition同义词。
shard:ES,MongoDB
region:Hbase
tablet:Bigtable
vnode:Cassandra
分区方式
基于关键字分区。
区间查询特性良好。每个分区可以关键字顺序查找。
基于关键字hash分区。
数据均匀分布。特定模式会数据倾斜,造成热点。
折中。如Cassandra。
复合主键第一列可hash分区,其他列用作SSTable的排序。
第一列分布均匀,其他列支持区间查找。
一致性哈希:特殊的动态分区方式。
适合缓存不适合持久化存储。
分区再平衡涉及节点少。
二级索引
基于文档。利于写,ES、Cassandra。
本地索引。每个分区独立,维护自己的二级索引。
并行查询,读延迟放大。
基于词条。利于读。
分区的全局索引。
单个文档更新,如果涉及多个不同分区的二级索引,写放大显著,通常异步。
分区再平衡
原因:
查询压力增加,需要更多CPU。
数据规模增加,需要更多硬盘。
节点故障,需要其他节点接管。
目标:
负载、存储在集群中分布均匀。
平衡过程中正常提供读写服务。
避免不必要的迁移,加快过程减少网络磁盘I/O影响。
触发方式:
自动。节点负载过重可能被认为失效,再平衡会加重负载,可能雪崩。
手动。
取模
mysql分库分表
迁移过程中数据在节点间复制,需要双写或者复制停写,读写受影响。
再平衡成本高。
节点N发生变化,每个节点都有数据迁移。
节点N发生多次变化,同一条数据多次迁移。
固定数量分区
ES
初始创建远超节点数的分区,节点->分区一对多。
新增节点时只需要调整分区、节点映射关系。
不影响节点的读写。
成本低。
动态分区
Hbase
初始预分区,或者集中在一个分区,节点->分区一对多。
分区数据量大于阈值则分裂,小于阈值则合并。
按节点比例分区
Cassandra
初始时每个节点具有固定数量的分区。Cassandra默认1节点->256个分区。
新增节点加入时,随机选择现有分区分裂拿走一半数据。
请求路由
客户端连接任意节点,节点转发到目标节点。
gossip协议同步集群状态,如Cassandra。
客户端连接路由层,路由层转发到目标节点。
zk同步集群状态,如hbase、codis。
客户端感知分区节点,直连目标节点。
样例:redis的三种集群方案
事务
ACID
事务隔离级别
重试中止事务的问题:
超时认为已成功的事务未成功,重试需要保证幂等。
系统负载导致错误,重试更糟,需要重试上限、指数回退。
永久系统故障导致,重试无意义。
重试有除DB外的操作,如短信,需要分布式事务。
重试失败,需要补偿。
分布式系统问题
故障->部分失效。
不可靠网络
client->network->server->network->client,都有可能出问题。
超时是检测故障唯一可行的方法。
网络采用分组传输,动态分区。是可变性和可靠性的权衡。
优点是可以用较高的资源利用率应对突发流量。
缺点是数据可能包拥堵排队,造成延迟的波动,这种异步网络的延迟是没有上界的。
不可靠时钟
分类
墙上时钟。绝对时钟,可以和NTP同步。
如 System.currentTimeMillis()从1970.1.1开始的毫秒,不含闰秒。
同步时如果本地时钟远快于NTP服务器,会直接回拨本地时钟。
单调时钟。相对时钟,可以测量时间间隔(超时),NTP不同步。
如 System.nanoTime。
依赖时钟的风险
依赖绝对时间戳,时间不同步,可能产生因果倒序。优先考虑基于递增计数器、时钟置信区间。
LWW前因覆盖后果。
依赖相对时间戳,进程暂停,产生冲突。
根据时间校验租约->暂停->处理。可能暂停完租约过期,和其他节点处理冲突。
可以暂停前通知其他节点、大对象不回收定期重启等应对进程暂停问题。
不可靠信息
真相由多数节点决定,节点不能根据自己的信息判断自身状态。//TODO zk故障全公司服务重启
无意误操作。如进程暂停,进程误以为自己还是Master。
应对:Fencing令牌,拒绝旧令牌的操作。
拜占庭故障。如软件bug、恶意攻击。
应对:鉴权、加密等。
抽象模型
计时模型。网络是否有上界延迟。
同步模型。
部分同步模型。
异步模型。
节点失效模型。
崩溃终止
崩溃恢复。
拜占庭失效。
普遍情况:部分同步+崩溃恢复。
一致性与共识
事务隔离:处理事务并发时的各种临界条件。
分布式一致性:针对延迟、故障等协调副本状态。
可线性化
最强一致性模型。
基本思想:一个系统看起来只有一个副本,所有操作都是原子的。
使用场景:
加锁和主节点选举。
唯一性约束。主键、用户名等。
跨通道的时间依赖。消息消费在图片存储完成之后。
实现方式。考虑容错必须多冗余,涉及复制,只有共识算法可靠。
共识算法。VSR,Paxos,Raft,Zab
主从复制。从唯一节点读取。
使用快照隔离、脑裂则非线性化。
多主复制。非线性化。
无主复制。dynamo风格。
如果网络延迟,在写确认之前读取,仍然非线性化。
顺序保证
因果一致性弱于可线性化。偏序关系。
因果关系可以被排序(happens-before)
并发关系无法被排序
Lamport时间戳。
唯一:计数器-存储节点ID的键值对
因果一致:节点追踪并维护接触的最大计数器,请求中带上该计数器。
事务与共识
共识的等价问题:
线性化的CAS寄存器
原子事务提交
全序广播
锁与租约
成员协调
唯一性约束
解决方式
单个主节点。
主节点失效:等待恢复、认为介入、共识算法选新主节点。
共识算法的要求:
安全性:
协商一致性。所有节点接收相同的决议。
诚实性。所有节点只能做一次决定。
合法性。结论一定是某个节点提出的。
活性:
可终止性。少于一半节点崩溃可达成结论。
————————————————
版权声明:本文为CSDN博主「娟宝宝萌萌哒」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_40369829/article/details/105277575