分库分表正确的拆分手段
垂直分表、水平分表、垂直分库、水平分库
不同场景下的分表方案
- 垂直分表:结构不同,数据不同(表级别)
- 水平分表:结构相同,数据不同(表级别)
不同场景下的分库方案
- 垂直分库:结构不同,数据不同(库级别)
- 水平分库:结构相同,数据不同(库级别)
- 另类的分库方案
- 主从方案
- 多主方案
分库分表后带来的“副作用”解决方案
垂直分表后带来的隐患
垂直分表后当试图读取一条完整数据时,需要连接多个表来获取,不算大问题
水平分表后带来的问题
多表联查问题(Join)
- 根据分表规则,去确定要连接哪张表后再查询。
- 连表获取1~3个字段,可以另一张表中设计冗余字段,避免连表查询。
增删改数据的问题
根据分表规则,到对应表操作
聚合操作的问题
- ①用第三方中间件完成,如ES。
- ②定期跑脚本查询出一些常用的聚合数据,然后放入Redis缓存中,后续从Redis中获取。
- ③从所有表中统计出各自的数据,然后在程序中作聚合操作。
垂直分库后产生的问题
跨库Join问题
- 常用的字段冗余到表中,避免跨库连表。
- 同步数据,通过广播表/网络表/全局表将对应的表数据直接完全同步一份到相应库中。
- 系统中组装数据,通过调用对方服务接口的形式获取数据,然后在程序中组装后返回。
分布式事务问题
- TTC事务补偿模式。
- MQ最终一致性事务模式。
部分业务库依旧存在性能瓶颈问题
再做水平分库
水平分库后需要解决的问题
聚合操作和连表问题
解决思路和水平分表时一样
数据分页问题
常用的分页数据提前聚合到ES或中间表,运行期间跑按时更新其中的分页数据。
ID主键的唯一性问题
- ①通过设置数据库自增机制的起始值和步长,来控制不同节点的ID交叉增长,保证唯一性。
- ②雪花算法生成有序的分布式ID
- ③利用第三方中间件生产ID,如使用Redis的incr命令、或创建独立的库专门做自增ID工作。
数据的落库问题
- 连续分片:每个节点负责存储一个范围内的数据,如DB1:1500W、DB2:5001000W…。
- 取模分片:通过整数型的ID值与水平库的节点数量做取模运算,最终得到数据落入的节点。
分库后程序怎么访问数据库?
中间件,当当网:Sharding-Sphere-Proxy
主从
主从复制架构概述
主从架构中必须有一个主节点,以及一个或多个从节点,所有的数据都会先写入到主,接着其他从节点会复制主节点上的增量数据,从而保证数据的最终一致性
使用主从复制方案,可以进一步提升数据库的可用性和性能
- ①在主节点宕机或故障的情况下,从节点能自动切换成主节点的身份,从而继续对外提供服务。
- ②提供数据备份的功能,当主节点的数据发生损坏时,从节点中依旧保存着完整数据。
- ③可以基于主从实现读写分离,主节点负责处理写请求,从节点处理读请求,进一步提升性能。
存在的问题
- ①硬伤:木桶效应,一个主从集群中所有节点的容量,受限于存储容量最低的哪台服务器。
- ②数据一致性问题:由于同步复制数据的过程是基于网络传输完成的,所以存储延迟性。
- ③脑裂问题:从节点会通过心跳机制,发送网络包来判断主机是否存活,网络故障情况下会产生多主。
解决方案 - 第一个问题只能靠加大服务器的硬件配置解决
- 第二个问题相对来说已经有了很好的解决方案(后续讲解)
- 第三个问题则是部署方式决定的,如果将所有节点都部署在同一网段,基本上不会出现集群脑裂问题。
MySQL中的主从复制技术
Bin-log日志实现
MySQL数据同步的原理
两种数据同步的方式
- 主节点推送:当主节点出现数据变更时,主动向自身注册的所有从节点推送新数据写入。
- 从节点拉取:从节点定期去询问一次主节点是否有数据更新,有则拉取新数据写入。
基于主从模型的不同架构
- 一主一从/多从架构
- 双主/多主架构
- 多主一从架构
- 级联复制架构
- 主从架构小结
- 一主多从架构:适用于读大于写的场景,采用多个从库来分担数据库系统的读压力。
- 多主架构:适用于读写参半的场景,采用多个主库来承载数据库系统整体的读写压力。
- 多主一从架构:适用于写大于读的场景,采用多个主库分担写压力,单个从库承载读压力。
- 级联复制架构:适用于读大于写的场景,采用单个从节点来分担从库对主库造成的I/O压力。
主从复制数据的方式
异步复制
当主节点接收到一个客户端的写请求后,先会往自身写入数据,自身数据写入成功后,就会立马向客户端返回写入成功的信息,对于从节点的数据,会在其他的时间内再异步复制过去。
同步复制
当主节点接收到一个客户端的写请求后,先会往自身写入数据,接着会去要求其他从节点也写入数据,当从节点的数据写入完成后,最终才会向客户端返回写入成功。
半同步复制
会先写入到主节点中,接着主节点会向所有从节点发送一个写入数据的请求,但半同步模式中无需等待所有从节点全部写入完成后再返回,而是只要有一个从节点写入成功并返回了ACK,则会直接向客户端返回写入成功,这样既能够保证性能,又能够确保数据不丢失。
增强式半同步复制/无损复制
延迟复制
从节点的SQL线程并不会立刻解析日志执行,而是等待一段时间后再解析日志执行,这个等待的时间可以由开发者来配置,一般建议设为3~6小时之间
并行复制
GTID复制
GTID(Global Transaction ID)也就是全局事务标识符
- 组复制
- 并行复制
主从数据一致性的解决方案
改变业务逻辑
对业务做一定更改,比如当用户立即修改数据后,因为在从库读不到数据,所以先显示一个审核状态,这样能够给出用户的反馈,从而避免用户再次重复操作
更改复制方式
全同步或半同步模式
调整数据库架构
- 升级服务器硬件,并将架构恢复成单库架构
- 升级到分库分表架构
引入第三方中间件
引入Canal中间件来监控主节点的Bin-log日志