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

臭大佬 2021-01-12 15:05:21 184
php  MYSQL 
简介 mysql千万数据级分表设计及实现方案

理论

针对系统数据表日渐增长的数据量,分库分表是减少数据库压力,增加db操作效率的常见解决方案。

在讨论之前,先了解几个概念

垂直分割

垂直拆分就是要把表按模块划分到不同数据库表中。

垂直拆分用于分布式场景。

当大团队在做电商项目的时候,基本上都会将一个项目进行拆分,拆分成n个小项目

这样做的好处就是,基于逆向服务架构,会拆分多个小项目,每个小项目都有自己单独的数据库,这样的话小项目之间互不影响。这样叫做垂直分割。

比如:会员数据库、订单数据库、支付数据库等等这样来分

可以减低开发团队之间的耦合度。就比如,某个团队把一个数据库弄挂了,对另外的团队基本没有影响。假如全部用的一个数据库,是不是全部都挂了,所有用到那个数据库的团队项目进度都要延期。

水平分割

垂直切分只是把表按模块划分到不同数据库,但没有解决单表大数据量的问题,就如问题中的用户操作日志表一样,而水平切分就是要把一个表按照某种规则把数据划分到不同表或数据库里。

通俗理解垂直分割和水平分割:水平拆分行,行数据拆分到不同表中, 垂直拆分列,表数据拆分到不同表中

取模算法

假设我们是saas系统,我们根据商户的shop_id分成10个表,这个时候我们可以对数据的shop_id10进行求余,然后对于不同的余数进行分表。

设计思路

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

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

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

一是根据自增主键进行哈希取模,将数据均分到n张表中;该方案最简单,且最合适,拆分后数据分布均匀。
二是无自增主键,选取的分表id由特定的方式生成,则需先确定分表id生成逻辑,根据该逻辑确定取模计算的逻辑,以保证数据均分。

案例分析

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

支付详情表

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

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

用户积分表

1、数据表结构分析:4kw数据量级、主键 id非自增、读多写少,常根据uid进行查询

2、方案设计:

采用uid作为分表键,研究uid生成逻辑为16位 (时间戳+机器ID+业务编码(细节不赘述);确定分表计算方案为右移7,保证取模方式合理,数据均分到表中。

3、实现细节

1)分表前,创建新表,将老表数据同步到新表(DTS阿里云dba方案)

2)修改代码,读取老表数据,同时双写(老表成功即为成功)

3)修改代码,读新表,继续双写(新表写成功即为成功)优化:修改读取配置,开关—切换读取新老表数据

4)稳定后,停止老表读写

4、问题分析

问题及方案

问题一:热点数据

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

解决方案

热点问题可通过对热点数据进行缓存,例如将用户的数据缓存起来。扩展问题:缓存与db的数据一致性及及时性

问题2

联合查询问题,分表后,如何返回某商家所有用户订单。

解决方案

根据商家id可进行异构索引表创建,即记录uid表的商家维度操作,将uid、商家id、订单id等作为一张全新索引表,记录关联关系。查询时可通过先查询索引表,找到对应分表键,再根据分表键单表路由。

注意

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

文章参考:https://blog.csdn.net/Daybreak1209/article/details/79858080
https://blog.csdn.net/Daybreak1209/article/details/80257508