漫谈分布式数据复制和一致性!

文章内容收录到个人网站,方便阅读hardyfish.top/

文章内容收录到个人网站,方便阅读hardyfish.top/

引子

在分布式系统中,出于多个原因,我们会希望将数据库分布到多台机器上:

  • 可伸缩性:如果数据量、读取负载、写入负载超出单机的处理能力,可以将负载分散到多台计算机上
  • 容错/高可用性:在单台机器故障的时候提供冗余,一台故障时,另一台可以接管
  • 延迟:如果你的用户分布在全国乃至全球范围,可以在多个地点部署服务器,以保证用户可以从最近的数据中心获取服务

共享内存架构:更高端的机器(垂直伸缩),成本增长快于线性增长、容错能力有限

共享磁盘架构:多个独立的处理器和内存,数据存储在共享的磁盘阵列,这些磁盘通过快速网络连接,但竞争和锁定的开销限制了共享磁盘方法的可伸缩性

无共享架构:每个节点只使用各自的处理器、内存和磁盘,也是最普遍的方式

复制:主从同步

复制意味着在通过网络连接的多台机器上保留相同数据的副本。

常见的复制算法分:单领导者、多领导者、无领导者

图:基于领导者的主从复制

同步复制和异步复制

同步复制的优缺点:更强的一致性保证;从库故障,主库无法处理写入操作,因此将所有从库都设置为同步的是不切实际的 ==> 半同步、链式复制

异步复制:不受从库状态影响,但写入不能完全保证持久性

从库宕机:追赶恢复

主库宕机:故障切换(手动或自动),思考:当老主库重新加入集群,未复制的写入怎么办?

复制延迟问题

读己之写(read-your-writes consistency)

  • 个别场景读取走主库(例如,若档案只能由用户自己编辑,对于用户自己的读取访问可以走主库)
  • 监控从库的复制延迟
  • 记录客户端上一次写入的时间戳或者序列号(跨设备问题)

单调读

确保每个用户总是从同一个副本进行读取

一致前缀读

写入按照某个顺序发生,读取也要按同样的顺序出现(多分区时会有这个问题,因为不存在全局写入顺序)==> 有因果关系的写入相同的分区

缓解复制延迟问题的相关实践参考

freno

github.blog/2017-10-13-...

分片(Sharding)

也称为分区(partitions),对于非常大的数据集或非常高的吞吐量,仅仅复制是不够的。

分区的方式

  • 按键的范围(不均衡问题)
  • 按键的散列(失去高效执行范围查询的能力 => 组合索引思路)
  • 热点消除(分割热点键)

关系型数据库的分库分表

分片方式

拆分方式 解释
垂直分库 按微服务分库
垂直分表 冷字段大字段拆分,减少单条记录大小
水平分表 单表记录量变少
水平分库 进一步将单表数据分布到多个实例,突破单实例限制,会引入分布式事务问题

分片下的执行流程

常见的分片与路由策略

Sharding JDBC 分片策略参考

Sharding JDBC 路由方式参考

分片策略 相关算法 解释 备注
标准分片 (StandardShardingStrategy) PreciseShardingAlgorithm 如果选择这种策略,PreciseShardingAlgorithm 必选 适用于 = ,in
RangeShardingAlgorithm between,< , >
复合分片 (ComplexShardingStrategy) 直接将分片键值组合以及分片操作符透传至分片算法,完全由应用开发者实现
行表达式分片 (InlineShardingStrategy) t_user_$->{u_id % 8} 表示t_user表根据u_id模8,而分成8张表,表名称为t_user_0t_user_7 推荐,且为默认的策略
Hint 分片 (HintShardingStrategy) 通过Hint指定分片值而非从SQL中提取分片值的方式进行分片的策略 对应强制路由

分布式主键生成方式

  • 指定设置起始值和步长(引入额外的运维规则,使解决方案缺乏完整性和可扩展性)
  • SnowFlake
  • 美团 Leaf
  • 百度 UidGenerator

实践资料

Sharding JDBC 分库分表配置参考

常见注意事项

  • 查询语句尽量使用分片键,避免广播路由
  • 不支持 INSERT ON DUPLICATE KEY UPDATE (sharding-jdbc 的限制)
  • 不支持 REPLACE INTO
  • 4.x不支持子查询,支持的版本子查询和外部也都必须指定一定的分片键
  • 慎用分页,不要在全分片扫描的时候使用非常大的offset,可能导致OOM (limit offset, count会被改写为limit 0, offset+count,该条查询语句会到每个分表中都捞取offset+count 这么多条数据,然后全部存到内存里,数据条数是分表数*(offset+count),有可能会导致OOM的情况发生)
  • 单库单表转分库分表简化 roadMap

分区带来的问题

《高性能MySQL》:如非必要,尽量不分片

  • 架构复杂性的提升
  • 分区不平衡问题(resharding)
  • 分布式事务问题
  • 决定分片前的考虑:索引、缓存、读写分离是否已足够、冷数据归档...

文章内容收录到个人网站,方便阅读hardyfish.top/

参考文献

相关推荐
计算机学姐1 分钟前
基于python+django+vue的影视推荐系统
开发语言·vue.js·后端·python·mysql·django·intellij-idea
小筱在线6 分钟前
SpringCloud微服务实现服务熔断的实践指南
java·spring cloud·微服务
luoluoal11 分钟前
java项目之基于Spring Boot智能无人仓库管理源码(springboot+vue)
java·vue.js·spring boot
ChinaRainbowSea16 分钟前
十三,Spring Boot 中注入 Servlet,Filter,Listener
java·spring boot·spring·servlet·web
小游鱼KF19 分钟前
Spring学习前置知识
java·学习·spring
扎克begod23 分钟前
JAVA并发编程系列(9)CyclicBarrier循环屏障原理分析
java·开发语言·python
青灯文案125 分钟前
SpringBoot 项目统一 API 响应结果封装示例
java·spring boot·后端
我就是程序猿35 分钟前
tomcat的配置
java·tomcat
阳光阿盖尔41 分钟前
EasyExcel的基本使用——Java导入Excel数据
java·开发语言·excel
二十雨辰42 分钟前
[苍穹外卖]-12Apache POI入门与实战
java·spring boot·mybatis