数据库数据量增多,数据操作开销变大,物理服务器资源有限,数据量过大产生产生的慢查询会拖累整个服务,可以通过分库分表进行优化。
分库就是把一个数据库按实际场景切分成多个库,再将数据表分散到多个库中。
分表就是把一个数据库中的数据表拆分成多张表,防止单表过大。
都是为了解决数据量过大的问题,由垂直划分和水平划分两种。
垂直划分:将一张表的数据,根据场景切分成多张表,可以将长度比较的且不常用的信息,移动到扩展表。
水平分表:将一张大表拆分成多个结构相同的子表,可以按某个字段进行业务划分,按照数量划分...
1. 分表的实现方式
分表逻辑一定是在一个公共,可复用的位置来实现。一般有两种选择:①在公共包里实现;②在一个中间件服务实现
公共包实现:本地依赖包,即将分表逻辑写在公共的代码库里,每个需要调用服务的客户方都集成该公共包,就接入了自动分表的能力。这种方式简单,不引入性的组件,不增加运维难度。缺点是就公共包更改后每个客户端都要更新。
中间件实现:可以是服务级别的中间件,有自己独立的进程,通过该进程来调用数据库,这样分表逻辑就是中心化,完全可控的,代理服务就属于这类。优点是方便更改、耦合性低、架构清晰。缺点是增加了运维成本。
2. 针对现有表做拆分
在设计之初就考虑清楚,设计一个长期稳定的分表策略,尽量不要对已有表进行拆分。对老项目拆分时需要考虑如下问题:分表过程中是否可以停服,不停服怎么保证数据一致性?
如何在不停服的情况下进行拆分?
可以通过几个阶段操作:
- 双写读老阶段:通过中间件,对write sql同时进行两次转发,也就是双写,保持新数据一致,同时开始历史数据拷贝。本阶段建议施行一周;
- 双写双读阶段:采用灰度策略,一部分流量读老表,一部分流量读新表,读新表的部分在一开始,还可以同时多读一次老表数据,进行比对检查,观察无误后,随着时间慢慢切量到新表。本阶段建议施行至少两周;
- 双写读新阶段:此时基本已经稳定,可以只读新表,为了安全保证,建议还是多双写一段时间,防止有问题遗漏。本阶段建议周期一个月;
- 写新读新阶段:此时已经完成了分表的迁移,老表数据可以做个冷备。