mysql千万数据级分表设计及实现方案

    针对系统数据表日渐增长的数据量,分库分表是减少数据库压力,增加db操作效率的常见解决方案。就目前项目系统而言,数据量级基本多张表已达3kw至6kw的量级。下面对笔者针对系统db结构,结合O2O业务特性整理的分表设计思路及实践方案的讨论。

设计思路:

1、首先确定是否要分表:就一般系统而言,数据量达到kw级别,慢sql数量增多,基本就需要考虑分表操作。

2、确定分成几张表:这个根据数据增长量估算,简言之,当前数据量分成多少份,结合当前业务量,估算本次分表后,可满足多少年内稳健的数据服务。

3、拆分方案:就拆分方案而言,一般采取两种思路:

    1)一是根据自增主键进行哈希取模,将数据均分到n张表中;该方案最简单,且最合适,拆分后数据分布均匀

    2)二是无自增主键,选取的分表id由特定的方式生成,则需先确定分表id生成逻辑,根据该逻辑确定取模计算的逻辑,以保证数据均分。

案例分析:

下面采用项目中两个case分表说明:

case1 支付详情表:

1、数据表结构分析:6kw量级、自增主键、数据插入查询多,更新少、日增量3k条

2、方案设计:采用自增主键取模8,分为8张表。

case2 用户积分表:

1、数据表结构分析:4kw 数据量级、主键 id非自增、读多写少,常根据uid进行查询
2、 方案设计:
    采用uid作为分表键,研究uid生成逻辑为 16位 (时间戳+机器ID+业务编码(细节不赘述);确定分表计算方案为 右移7,保证取模方式合理,数据均分到表中。
3、实现细节
1)分表前,创建新表,将老表数据同步到新表(DTS阿里云dba方案)
2)修改代码,读取老表数据,同时双写(老表成功即为成功)
3)修改代码,读新表,继续双写(新表写成功即为成功) 优化:修改读取配置,开关--切换读取新老表数据
4)稳定后,停止老表读写

4、问题分析

问题1:根据uid进行分表,同一个uid的所有记录都会落入同一张表中。若该uid为高频用户,则该uid假设有1w条订单记录,这极有可能导致针对该uid的订单查询缓慢;另外遇到订单id或其他维度的key查询,也会导致热点问题。而热点数据又大概率上会大量增长。
问题2:联合查询问题,分表后,如何返回某商家所有用户订单。

问题1解决方案:热点问题可通过对热点数据进行缓存,例如将用户的数据缓存起来。扩展问题:缓存与db的数据一致性及及时性(在此不做讨论)
问题2解决方案:根据商家id可进行异构索引表创建,即记录uid表的商家维度操作,将uid、商家id、订单id等作为一张全新索引表,记录关联关系。查询时可通过先查询索引表,找到对应分表键,再根据分表键单表路由。

5、注意:
    1)数据尽可能平均拆分,避免热点问题;如遇热点问题,采用对热点数据进行缓存等方式减少热点数据访问压力
    2)减少全局扫描,针对带有分库分表键的sql直接经路由后查指定表,但针对无分表主键,例如case中商家所有数据,则只能通过查询所有表后,再将数据聚合后返回-事务边界过大。此时可通过创建索引表,用于记录所有表的crud操作(空间换时间)。创建以商家id为索引的表,通过先查卖家所有记录,得到所有用户id,再拿uid 为key去表里查就变为带有分库分表键的查询。极致的还可能创建两张表,除了分表key不一样,其他字段均相同。即可通过uid、商家id进行查询。但冗余太大如无必要,一般不采取全表复制。

猜你喜欢

转载自blog.csdn.net/daybreak1209/article/details/79858080
今日推荐