分库分表实战
背景
商品评价这一块,评价信息单表存储,主要包括一些基本评价信息,商品id,订单id,买家id和卖家id,当时DB量级已经达到上亿,会出现一些慢SQL
业务场景分析
根据分库分表,可以得出一个期待的结果
- 独立的评价库,这个库只保存评价相关信息
- 采用水平分表,将原表的数据,拆分到1024(数量可以自定义)张分表中(如果拆分合理,则单表数据在30W-40W)
需要考虑的问题就是如何水平拆分
- 商品详情的评价查询:根据商品ID进行查询
- 卖家管理端查询所有评价:根据卖家ID进行查询
- 买家评价管理:根据买家ID进行查询
- 订单列表的评价信息:根据订单ID进行查询
粗略可以设定两种方案:
- 上面四种场景,显然是根据商品ID查询的量最大,如果根据商品ID进行分表,那么商品的评价都落在一个分表中,此时查询不会出现跨表,但是另外三种查询会导致跨表;同样换成卖家ID也会导致其他三个查询跨表
2.建立一张附表,只保存如下信息
rateId:评价ID
itemId:商品ID
sellerId:卖家ID
buyerId:买家ID
orderId:订单ID
根据rateId进行分库分表,这样每次查询,先通过附表,查询对应的评价ID,然后拿rateId到分表去获取评价信息
设计与实现
方案设计
前面给了两种方式,一种根据商品ID进行分表,一个是建立一个附表然后根据rateId进行分表,首先是分表规则,我嗯选择最简单的额方式,根据id%12进行取模
分析两种方式的优劣
- itemID分表
- 优点
- 实现简单,无需附表,不用考虑数据不一致的问题
- 可以支持详情评价列表复杂的排序逻辑
- 性能更优能,少了一张附表
- 缺点
- 非itemId查询会跨表
- hash不均匀,导致单表数量比较多 2.rateId分表方案
- 优点
- 支持前面的几种查询,不过要先查询出rateId
- 但表数据量分布均匀
- 缺点
- 复杂查询条件支持不友好,排序、过滤需要依赖一些评价信息的场景
- 插入和更新的时候,都需要同步更新附表,复杂度更高(需要满足表的事物)
- 每次查询都需要通过附表查询rateId,效率比较低 方案选择 通过实际分析,选择了根据itemId进行分表查询,理由如下:
- 业务逻辑简单,后续维护方便
- 线上的sql,95%根据itemId进行查询
- 上层有一层根据solr的搜索,因此根据buyerId,sellerId等可以走搜索,不需要进行db的多表联合查询
- 附表虽然结构简单,但是单表的最终数量依然会很大 所以:
- 优点
db :rate000 ~ Rate003
table :ItemRate0000 ~ ItemRate1023
其中映射规整:
tableIndex = itemId % 1024 ---> 分表名 如 ItemRate0122
dbndex = itemId % 1024 /256 ---> 分表名 如 ItemRate001
步骤计划
两种方式
- 方案一:采用双写
- 创建DB
- 服务的sql改造,主要是所有的sql,都要有一个新的分库分表的方式
- 线上开始双写(新增一条评价,即写入旧表,也写入新表)
- 全量将旧表数据导入新表
- 线上读流量切换到新表,验证是否有问题
- 所有关注旧表binlog业务,全部迁移到关注新标的binlog(需要dba支持,新标有1024张,不可能关注全部topic,需要dba提供binlog整合)
- 关闭双写,所有写操作直接切换到新表
- 方案二:基于db的binlog实现的异步同步方式
- 创建DB
- 服务的sql改造,主要是所有的sql,都要有一个新的分库分表的方式
- 开启增量,将某个时刻开始之后所有更新的数据,通过异步方式增量同步到新表
- 开始全量,将之前的数据全部导入到新标
- 线上读切换新表,验证服务是否有问题
- 所有关注旧表binlog业务,全部迁移到关注新表binlog
- 线上切换写操作到新表
- 增量完毕后,关闭增量
两种方案本质上没有太大区别,第一种双写需要自己保障双写成功;后面增量的方式,一般DBA会有比较好的方案实现增量同步(一般选择第一种方案)
注意事项
- 全量迁移,如果dba没有提供相关工具,只能自己写,可以找一台机器,部署服务利用jdbcTemplate扫表,实现全量数据插入
- 双写需要注意双写失败
- 数据最后需要对账比较
小结
- 分库分表
- 一般而言,当量级达到百万时,就需要考虑分库分表了,不同业务有自己的独立的库
- 根据表中某些列进行分表,将大表数据拆分到分表中
- 大表拆分为小表
- 实现步骤
- 创建DB
- 服务的sql改造,主要是所有的sql,都要有一个新的分库分表的方式
- 线上开始双写(新增一条评价,即写入旧表,也写入新表)
- 全量将旧表数据导入新表
- 线上读流量切换到新表,验证是否有问题
- 关闭双写,写直接切换到新表
Enjoy Reading This Article?
Here are some more articles you might like to read next: