面试连环炮系列(十七):你们的项目为什么要分库分表

面试连环炮系列(十七):你们的项目为什么要分库分表

  1. 你们的项目为什么要分库分表?
    随着业务的发展,公司项目的日活翻了几十倍,订单表Order每月新增数据100万左右,有部分场景查询效率不太高了。通过升级配置、业务规避、缓存集群、归档历史数据等手段,也能够满足当前的查询要求。但是业务是呈加速度增长的,未来的数据会更多。虽然深知过早优化的弊端,但是数据分片一定要做的,不可能等到崩了再做,于是决定分库分表。

  2. 具体怎么实施的,遇到了哪些问题?
    我们采用了中间件Mycat,它是一个数据库代理,支持多种分片策略。由于只是代理,改造代码的工作量少一些。我们主要对订单表order实施分库分表,一般会有几个方面的问题要解决:

    • 分布式唯一ID:我们的订单编号在一开始就是全局唯一ID,采用zookeeper生成的,格式是YYMMDDHHMMSS+ZK自增ID,比如2012091015163000002,所以分布式ID不是问题。
    • 分片策略:我们选择按Hash取模的方案,比起按范围分片,这种方式数据分布比较均匀。我们希望此次分片操作能满足未来五年的数据增长,于是设定数据库12个,每个库中有1024个数据表,订单编号2012091015163000002,按照上述的路由策略,可得:
      中间变量 = 2012091015163000002 %(12 * 1024);
      库序号 = 取整(中间变量/1024;
      表序号 = 中间变量 % 1024;
    • 查询改造:由于Mycat不支持某些SQL写法,比如Order by字段必须出现在select中,要逐一排查改写。
    • 分布式事务:创建订单数据的逻辑没有事务,不存在分布式事务的困扰。
    • 不停机部署上线:在整个改造过程中,我们的系统始终正常运行,保证服务的稳定性和数据的完整性。
  3. 详细说说不停机部署上线怎么做的?

    1. 数据库双写:采用中间件Canal订阅老库的增量数据,根据分片规则写入新库中。
    2. 迁移历史数据:根据新库最小create_time字段划分增量和历史数据,早于create_time的数据属于历史数据,利用迁移工具将数据迁移到新库中。
    3. 数据一致性:新老数据库数据总量是否一致。
    4. 改写后的代码上生产,并切换新数据源。
  4. Canal的原理你清楚吗?
    canal模拟MySQL slave的交互协议,伪装自己为MySQL slave,向MySQL master发送dump协议。MySQL master收到dump请求,推送binary log给canal,canal解析binary log对象(原始为byte流)。

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注