分库分表知识
为什么要分库分表?
单库, 单表的问题(痛点), 每个数据库的连接数都是有上限的。
- 查询瓶颈: 由于太多热点数据, 数据库缓存完全放不下, 只能放到磁盘中, 查询时候会产生大量磁盘IO, 导致查询缓慢, 占用连接, 最终可能导致无连接可用, 并且单表的数据量超过亿级后, 查询效率会变得越来越低, 并且由于需要扫描的索引树太多导致CPU使用率提升。
- 写入瓶颈: 单个库写入的性能是有上限的, 单库频繁的写也会产生大量的磁盘IO操作占用连接, 最终可能也会导致无连接可用, 分库分表后能解决这种问题, 并且由于分表后, 单表数据量少, 插入时索引的查找和更新成本更低, 效率会更快。
- 服务器瓶颈: 所有的读写都是在同一个库上的情况, 终有一天业务会增长到单体服务器资源完全支撑不起业务的写读而导致的宕机。
分库分表解决方案?
- 采用读写分离架构, 实现一主三从, 主库专门用于写, 从库通过读取binlog日志同步数据到从库, 读操作都走从库, MySQL自带就可以实现一主多从, 读写分离可以采用中间件。
- 垂直切分根据业务不同将表字段拆分, 拆分不同的库, 例如用户库, 用户相关不同的表。
- 水平切分将表实现多个分片表, 写操作的数据, 按照特殊字段hash算法取余后决定存储到那张表, 将一个业务的数据平均分到不同的表里面去。
- MySQL自带的一个分区功能
分库分表可选方案?
目前互联网上有许多的版本,比较知名的一些方案:
分库分表后的问题?
- 无法跨库连表查询, 尽量进行单表查询, 如果非要多表关联则需要进行建立关联索引表, 表里面是各个关联表的查询条件索引字段, 找到对应结果再去单表查询
- 主从延迟问题导致插入后查询可能查询不到, 采用强制查询走主库, 或者使用ShardingSphere中间件在写线程中有读操作都走主库
- 分布式事务问题, 解决方案是采用成熟开源的分布式事务解决方案
- 运维成本、 资源成本、 数据迁移问题
- 数据同步问题, 以前的单库单表, 变成需要同步多库多表
- 某些数据库函数不在支持, 批量插入根据分片规则可能也导致不支持
如何进行分库分表?
我们公司采用的是Apache ShardingSphere v4.1.1,
这个版本不分片的表还不支持, 所以使用了Spring+AOP实现多数据源支持针对分片的表
v5.x支持了自动识别, shardingjdbc不参与分库分表的配置处理方式
- 先考虑好恢复方案, 如果在分库分表途中出现了问题, 如何能最快速度的恢复
- 先从无关紧要的表, 进行分表, 然后进行测试, 最终到线上测试运行一段时间后, 没有问题再进行下一步略微重要的表进行分表
- 进行步骤2, 可以使用多数据源方案, 在需要进行分表的读写操作才走分表方案操作, 未分表的操作走以前操作
- 进行组织开发人员方案讲解, 说明那些SQL无法使用, 建议怎么使用
- 上线前经过充分的测试, 并提前列出有可能出现的风险点和解决方法
总之就是需要稳
总结:
如果单表没有达到瓶颈, 没有必要的进行分表
扩展
Spring中可以通过AbstractRoutingDataSource来实现多数据源管理 (spring boot使用AbstractRoutingDataSource实现动态数据源切换)
1