一、分库分表背景
老调常谈,直接原因是数据量的锅。传统IT/业务量较小的企业里也许很难体现出,而在大型互联网企业里,数据量增长巨快,像我们公司埋点数据的指标拍平后,每天有亿级别的数据。按阿里巴巴给出的开发规范,单表超过500w行就要考虑分表,因为此时单机的性能已经到瓶颈。
所以,后来牛人们提出分布式。一台机器顶不上,那就多台,人多自然力量大,化整为零来解决。
具体到数据的存储上,那就是按照一定的规则,将数据库划分到不同的库/表中,而后取数的时候去特定的存储位置上进行获取。
二、引入分库分表时机1
我们在编码过程中,分库分表可以在以下几个层次切入:
- 代码层
完全需要开发人员来编写分库分表的逻辑
- 框架层
开发人员扩展框架来实现分库分表
- 驱动层
由第三方实现驱动层的包,供开发人员调用。如Sharding-JDBC、TDDL等。
- 代理层
由第三方实现,启动服务伪装成数据库,接受业务端的连接。如MyCAT、Sharding-Proxy等。
- 实现层
底层存储数据的软件变更,如采用TiDB
三、分库分表实现
目前来说,无论从驱动层还是代理层的层面切入,第三方的实现流程大体都要经过如下几步:
- SQL解析
可以使用开源的SQL解析器,如阿里的Druid,或者采用ANTLR创建自己的SQL编译器
- SQL路由
SQL路由的意思是指根据传递的数据,经过特定规则能传递到正确的库/表来操作数据。如订单库中,根据用户id分库,然后依据订单id分表,来插入/更新订单信息。
在这个过程中,主要是规则的制定,特别是需要注意数据分库/表后的数据平均。常见的规则譬如取模、哈希和直接指定库/表(尾数为1落1库,尾数为2落2库,尾数为3落3库)等。
- SQL改写
经过SQL路由后,分库分表应用模块已经知道某条SQL语句对应的库及表,此时需要改写SQL语句的库/表让其执行在正确的库/表中。如:
SELECT id, order_id, user_id from demo_ds.t_order
可能会改写为:
SELECT id, order_id, user_id from demo_ds_0.t_order_0
-
SQL执行
-
结果归并
对于聚合类的查询,当从每个库/表中获取出聚合的结果,比如MAX
,分库分表模块还需要归纳,最终取出各个库/表中的最大值进行综合比较返回。