一、分库分表理论篇
什么是分库分表?
- 垂直分库
把数据库按照业务分库 - 垂直分表
将表按照列进行拆解 - 水平分表
为什么要搞分库分表?
- 数据库中的表太多----分库----微服务(应用和数据库都是单独的,比如说用户模块, 用户相关的表在单独的数据库上)
- 分业务库是为了减少数据库的访问压力,根据业务模块进行分库(一般为了体现分库 的好处,都是单独讲一个库进行部署到Linux)
- 记住:不要使用docker技术来部署数据库。
- 还有一种分库,主要是为了更好的去优化数据库的性能。
- 数据库中的表记录太多
- 水平拆表/水平分表
- 电商系统:增量表、订单、用户 -
- 不是什么表都要拆分
如何分库分表?
- 分库分表的方式
- 分库不分表
- 库内分表
- 分库分表
- 水平分表
- 取模/取余 【表中的id主键 % 要拆分的表的数量(3)】 真实表( t_user_0 t_user_1 t_user_2) 逻辑表 t_user
- 范围 【表中的id主键在0-10000,分到t_user_0 10001-20000 t_user_1 20001-30000 t_user_2
- 日期 【表中的日期列进行拆表】
- hash取余 hash(name) % 要拆分的表的数量(3)
分库分表存在的问题
- 跨库join问题
- ER分片(订单表和订单明细表、订单表和用户表)
Mycat ER分片
Sharding JDBC 绑定表 - 业务层将join拆分为多个持久层的调用。
- 全局唯一主键问题
- 分布式事务问题
- 跨库count、order by 、group by
分库分表的产品有哪些?
- 阿里的TDDL、Cobar
- 基于阿里Cobar开发的Mycat
- 当当网的sharding-jdbc —Apache
二、分库分表介绍
使用背景
- 当【表的数量】达到了几百上千张表时,众多的业务模块都访问这个数据库,压力会比较大,考虑对其进行分库。
- 当【表的数据】达到了几千万级别,在做很多操作都比较吃力,所以,考虑对其进行分库或者分表
数据切分(sharding)方案
数据的切分(Sharding)根据其切分规则的类型,可以分为两种切分模式:
- 垂直切分:按照业务模块进行切分,将不同模块的表切分到不同的数据库中。
- 水平切分:将一张大表按照一定的切分规则,按照行切分成不同的表或者切分到不同的库中。
切分规则
常用的切分规则有以下几种:
- 按照ID取模:对ID进行取模,余数决定该行数据切分到哪个表或者库中
- 按照日期:按照年月日,将数据切分到不同的表或者库中
- 按照范围:可以对某一列按照范围进行切分,不同的范围切分到不同的表或者数据库中。
切分原则
- 第一原则:能不切分尽量不要切分。
- 第二原则:如果要切分一定要选择合适的切分规则,提前规划好。
- 第三原则:数据切分尽量通过数据冗余或表分组(Table Group)来降低跨库 Join 的可能。
- 第四原则:由于数据库中间件对数据 Join 实现的优劣难以把握,而且实现高性能难度极大,业务读取尽量少使用多表 Join。
三、分库分表需要解决的问题
分布式事务问题
- 强一致性事务(同步)
- 最终一致性事务(异步思想)
分布式主键ID问题
- redis incr命令
- 数据库(生成主键)
- UUID
- snowflake算法(https://www.sohu.com/a/232008315_453160)
跨库join问题
- 通过业务分析,将不同库的join查询拆分成多个select
- 建立全局表(每个库都有一个相同的表)
- 冗余字段(不符合数据库三范式)
- E-R分片(将有ER关系的记录都存储到一个库中)
- 最多支持跨两张表跨库的join
跨库count、order by、group by问题
Sharding JDBC
具体Sharding JDBC用法示例参考Sharding JDBC官方网站