原因:解决超大容量问题,和性能问题
如何做:
垂直切分
- 垂直分库:解决的时表过多的问题
- 垂直分表:解决单表列过多的问题
水平切分
- 大数据表拆成小表
常见的拆分策略:
垂直拆分:
- 考虑因素包括技术的支撑,
- 业务是否有必要,
- er分片(相关联的表放在同一个库中,避免跨库)
水平拆分:
- 一致性哈希:userid%10,字段的选择很重要
- 范围切分:id在0-10000,好处是数据连续
- 日期拆分:把之前的数据放入备库
水平拆分的优点:
- 拆分规则抽象好,join 操作基本可以数据库做;
- 不存在单库大数据,高并发的性能瓶颈;
- 应用端改造较少;
- 提高了系统的稳定性跟负载能力。
水平拆分的缺点:
- 拆分规则不好抽象;
- 分片事务一致性难以解决;
- 数据多次扩展难度大;
- 跨库 join 性能较差。
分库分表拆分带来的问题
跨库join的问题
- 分表设计时尽量避免,
- 通过业务服务层通过接口调用等
- 全局表:(每个库都有相同的表)字典,常量(数据变更比较少),公共服务等,
- 做字段冗余(空间换时间的做法)
唯一主键问题
- uuid(值比较大,性能问题)
- snowflake(雪花算法)时间序列,机器标识,计数顺序号
- mongoDB
- zookeeper,sequences的实现
- redis,incrby
- 数据库表,同步获取自增的主键等
- 多个数据库表保证原子性,性能问题
数据源管理的问题
- 客户端模式,
也就是在每个应用程序模块中配置管理自己需要的一个(或者多个)数据源,直接访问各个数据库,在模块内完成数据的整合。比如可以依赖spring注解实现。中间代理模式,统一管理所有的数据源,后端数据库集群对前端应用程序透明。考虑到系统的复杂性和扩展性,建议第二种中间代理模式。虽然短期内需要付出的成本可能会相对更大一些,但是对整个系统的扩展性来说,是非常实用的。 - 中间件层面
上面的系统层面,需要的代码实现比较复杂,中间件是在数据集群前面加一层代理,比如Cobar、Mycat等数据库中间件。实用数据库中间件,对代码层面的实现是很大的解放。
如何切分,我们遵循如下原则
- 能不切分尽量不要切分;
- 如果要切分一定要选择合适的切分规则,提前规划好;
- 数据切分尽量通过数据冗余或表分组来降低跨库 Join 的可能;
- 由于数据库中间件对数据 Join 实现的优劣难以把握,而且实现高性能难度极大,业务读取尽量少使用多表 Join。
如何权衡当前公司的存储需要优化
- 提前规划(主键问题解决,join问题)
- 当前数据单表超过1000W,每天的增长量持续上升