雪花算法:https://www.sohu.com/a/232008315_453160
单元化:https://mp.weixin.qq.com/s/pPGppiQAySBEMZja0nwxkA
1 为什么需要分库分表
传统的项目结构将所有子系统的数据都交给一个mysql,无法支撑
这涉及到数据库性能的瓶颈:
1 数据库连接数有限:默认100个,单机最大16384
2 表数据量:单机表数量过多,表数据也过多
3 硬件问题:硬件资源不够
进行了数据库性能优化之后:参数优化、索引优化、读写分离,还是不够,因此需要最终方案:分库分表
2 分库分表概念介绍
一般在表的数量达到了几百上千时,考虑进行分库
数据达到千万级别时,考虑进行分库或分表
一般分库是必须的,这样才能用到多机
2.1 数据切分方案
按照切分规则,可分为垂直切分和水平切分
2.1.1 垂直切分
分库:按照业务模块进行切分,将不同模块的表切分到不同的数据库中
分表:按照字段的业务进行切分,将不同业务的字段切分到不同的表中,即大表拆小表(可以不分库,但是意义不大,性能瓶颈还是在单机)
此方案在表和数据过多的时候也不好,因为按字段、表切的本质是按照业务来划分的,而业务总是固定的那几个,如果数据过多,无法再继续拆分
因此建议使用水平切分,不要按字段、表切,而是按行切
2.1.2 水平切分
此方案必须分库:将一张大表按照一定的切分规则,按照行切分数据后,分到不同的库中的表
每个库都有相同的表,通过一定的规则,如hash,将数据分布在不同库上的表
ER分片:不同表有关联关系的字段要把值相同的放在同一个库里,可以避免跨库连接,还可以使用全局表来避免
规则:
按照ID取模
按照日期
按照范围
规则涉及分片键和分片算法,分片策略则是根据算法的选择得出的
2.2 切分原则
第一原则:能不切分尽量不要切分
第二原则:如果要切分,则一定要选择合适的切分规则,提前规划好,因为迁移是很困难的
第三原则:数据切分尽量通过数据冗余或表分组来降低跨库join的可能
2.3 分库分表需要解决的问题
2.3.1 分布式事务问题
一般采用补偿事务,即利用记录日志的方式来实现最终一致性
2.3.2 分布式主键ID问题
需要保证不同库上的表的主键ID不冲突
解决:本质就是由中间人来管理
1 redis的incr命令
2 数据库专门用一个表来生成主键
3 UUID(不建议:太长占空间,有可能重复)
4 snowflake算法:能在分布式系统中生成全局唯一且趋势递增的ID
2.3.3 跨库join问题
使用全局表或ER分片解决
全局表(也叫代码表)建议为数据少的,不经常改变的,如等级表
如果需要关联的表过大,则使用ER分片:将有ER关系的记录(行)都存储都一个库中
如果实在要跨库,则最多两张,三张就太慢了
3 分库分表实现技术
TDDL、Cobar、Mycat、Sharding-jdbc
现在常用的是Sharding-jdbc,取代了Mycat
4 无限扩容
由于数据库连接问题,分库分表并不能无限扩容,需要借助单元化来实现:https://mp.weixin.qq.com/s/pPGppiQAySBEMZja0nwxkA