在分布式系统中,出于多个原因,我们会希望将数据库分布到多台机器上:
可伸缩性:如果数据量、读取负载、写入负载超出单机的处理能力,可以将负载分散到多台计算机上
容错/高可用性:在单台机器故障的时候提供冗余,一台故障时,另一台可以接管
延迟:如果你的用户分布在全国乃至全球范围,可以在多个地点部署服务器,以保证用户可以从最近的数据中心获取服务
共享内存架构:更高端的机器(垂直伸缩),成本增长快于线性增长、容错能力有限
共享磁盘架构:多个独立的处理器和内存,数据存储在共享的磁盘阵列,这些磁盘通过快速网络连接,但竞争和锁定的开销限制了共享磁盘方法的可伸缩性
无共享架构:每个节点只使用各自的处理器、内存和磁盘,也是最普遍的方式
复制:主从同步复制意味着在通过网络连接的多台机器上保留相同数据的副本。
常见的复制算法分:单领导者、多领导者、无领导者
图:基于领导者的主从复制
同步复制和异步复制同步复制的优缺点:更强的一致性保证;从库故障,主库无法处理写入操作,因此将所有从库都设置为同步的是不切实际的==半同步、链式复制
异步复制:不受从库状态影响,但写入不能完全保证持久性
从库宕机:追赶恢复
主库宕机:故障切换(手动或自动),思考:当老主库重新加入集群,未复制的写入怎么办?
复制延迟问题读己之写(read-your-writesconsistency)
个别场景读取走主库(例如,若档案只能由用户自己编辑,对于用户自己的读取访问可以走主库)
监控从库的复制延迟
记录客户端上一次写入的时间戳或者序列号(跨设备问题)
单调读确保每个用户总是从同一个副本进行读取
一致前缀读写入按照某个顺序发生,读取也要按同样的顺序出现(多分区时会有这个问题,因为不存在全局写入顺序)==有因果关系的写入相同的分区
缓解复制延迟问题的相关实践参考
分片(Sharding)也称为分区(partitions),对于非常大的数据集或非常高的吞吐量,仅仅复制是不够的。
分区的方式按键的范围(不均衡问题)
按键的散列(失去高效执行范围查询的能力=组合索引思路)
热点消除(分割热点键)
关系型数据库的分库分表
分片方式分片下的执行流程常见的分片与路由策略
ShardingJDBC分片策略参考
ShardingJDBC路由方式参考
分布式主键生成方式指定设置起始值和步长(引入额外的运维规则,使解决方案缺乏完整性和可扩展性)
SnowFlake
美团Leaf
百度UidGenerator
实践资料ShardingJDBC分库分表配置参考
常见注意事项查询语句尽量使用分片键,避免广播路由
不支持INSERTONDUPLICATEKEYUPDATE(sharding-jdbc的限制)
不支持REPLACEINTO
4.x不支持子查询,支持的版本子查询和外部也都必须指定一定的分片键
慎用分页,不要在全分片扫描的时候使用非常大的offset,可能导致OOM(limitoffset,count会被改写为limit0,offset+count,该条查询语句会到每个分表中都捞取offset+count这么多条数据,然后全部存到内存里,数据条数是分表数*(offset+count),有可能会导致OOM的情况发生)
单库单表转分库分表简化roadMap
分区带来的问题《高性能MySQL》:如非必要,尽量不分片。
架构复杂性的提升
分区不平衡问题(resharding)
分布式事务问题
决定分片前的考虑:索引、缓存、读写分离是否已足够、冷数据归档...
作者:程序员清风链接:juejin.cn/post/