Mysql千万数据级分表设计及实现方案(2)附一致性哈希原理解析

首先,接着上篇博文:Mysql千万数据级分表设计及实现方案已经分析了自增id作分表key和全局服务id(16位)作分表key进行分表的两种设计方案。自增id优势在于简单,直接哈希取模即可分表完成。根据全局服务生成的16位用户id(或订单id)则需关注分表键生成策略,根据生成策略确定取模算法,保证数据尽量均匀分布。另外采取uid还得关注热点用户导致的数据热点问题,若出现热点问题,可针对热点数据做缓存处理,减少某几张表的数据存取压力。

下面根据项目实践来进一步总结分析分库分表设计及落地方案。

一、根据数据年增长量及业务增长量预估,确定分表数

以库中最大数据量作考量,分析如下:

1、交易账单表当前数据量:8kw

2、2017年增长:8kw

根据dba建议考虑分表后单表数据量不超过1kw估算,8kw/16=0.5kw *2年=1kw,若分成16张表可基本满足两年的数据增长。

 二、结合业务,每张表对应crud操作,确定分表key

在选择分表键,有两个点需要重点关注:

1、采用外部键作为分表键

因为一般查询业务都是根据订单id,用户id等具备业务属性key调用交易,选择这些key的好处在于业务线直接传入分表键,无需二次映射操作,直接路由即可。而劣势在于,键的生成策略外部控制,与业务线强耦合,且类型等受制。

对于公司如果提供全局的id生成,且各系统均采取该方式维护,则可以采取外部键。

2、选择自身生成id(pay_id)为分表键

业务线查询业务key(b_U_id|order_id),此时业务线对pay_id是无感知的,与交易交互仅通过业务线id或订单id,则需要:

方案1:考虑先查出分表key后路由(方案:查取缓存、或创建bid-pay_id的映射表)

方案2:根据业务线传入id做一次查询。每次操作多余一次查询,且查询分表在无分表key情况下,依次查。存在效率问题

最终选取2中方案1,建立业务表与分表键的映射表,且映射表同样进行分表,一次业务交互两次路由。

 三、根据业务背景,确定分表方式

垂直拆分

1、常见拆分场景

a). 大字段的垂直切分。单独将大字段建在另外的表中,提高基础表的访问性能,原则上在性能关键的应用中应当避免数据库的大字段

b). 按照使用用途垂直切分。例如企业物料属性,可以按照基本属性、销售属性、采购属性、生产制造属性、财务会计属性等用途垂直切分

c). 按照访问频率垂直切分。例如电子商务、Web 2.0系统中,如果用户属性设置非常多,可以将基本、使用频繁的属性和不常用的属性垂直切分开

2、拆分原则

一般讲长度短、访问率高的字段,拆分进入base表。其他字段放入extend表中。因为mysql通过行进行buffer缓存,长度短意味着能一次性存储更多行数的记录,最大量减少磁盘访问。

水平拆分

1、常见拆分场景

a). 比如在线电子商务网站,订单表数据量过大,按照年度、月度水平切分(时间维度range)

b). Web 2.0网站注册用户、在线活跃用户过多,按照用户ID范围等方式,将相关用户以及该用户紧密关联的表做水平切分(用户id range)

c). 例如论坛的置顶帖子,因为涉及到分页问题,每页都需要显示置顶贴,这种情况可以把置顶贴水平切分开来,避免取置顶帖子时从所有帖子的表中读取

3、两种方式的常见拆分方案:

1、hash取模:简单,路由方便;扩容不方便,进行rehash 二次扩容。

  一致性哈希:普通哈希优化-->一致性哈希

普通哈希case:

1、10个id,分2张表数据分布如下:

node1

0

2

4

6

8

node2

1

3

5

7

9

2、数据扩容,分成4张表数据分布如下(rehash操作):

node1

0

4

8

node2

1

5

9

node3

2

6

 

node4

3

7

 

数据迁移量:2、3、6、7 共4各节点数据需进行迁移,40%(其实这种计算方式不恰当,因为随着数据量增加,同样由2扩容到4,迁移量肯定小于40%)

3、不进行double扩容,而是采取增加或减少某个节点(仍然需要rehash)。例如增加1各节点后,数据分布:

node1

0

3

6

9

node2

1

4

7

 

node3

2

5

8

 

数据迁移量:2,3,4,5,8,9 共6各节点数据需进行迁移,60%

一致性哈希case:

先简单介绍原理:

1、将node节点数和id按照相同哈希算法(如md5、ascii)先计算出一个哈希值,则计算后的node值则可以看做分布在一个环上的节点。

2、将每个id计算的哈希值与node哈希值做对比,小于某node的,均分布在node后。

3、则此时进行节点新增时,再将需新增的节点按照同样的算法计算出哈希,按大小与原node哈希进行对比确定在环中的分布位置。再重复2中操作,确定需要迁移的数据。

同样10个id,先分2张表,采用一致性哈希算法操作如下:

1)计算分表键id及分表table(node)对应哈希值

id

0

1

2

3

4

5

6

7

8

9

哈希值

192

196

200

204

208

212

216

220

224

22

 

node

a

g

z

node哈希值

203

209

228

 

2)按照大小对比,进行分表操作

node a(203)所有id哈希值小于203的存放在203后

同理 node g(209)

同理 node z(228)

新增 node y(216)

0:192 

1:196 

2:200

4:208

5:212

6:216

7:220

8:224

9:228

 

       

3)此时再增加节点node 3,算出哈希值为216,则只需要将大于228的数据而小于216的部分,迁移到216上,即只需要迁移5、6

node a(203)所有id哈希值小于203的存放在203后

同理 node g(209)

同理 node z(228)

新增 node y(216)

不变

不变

7:220 

8:224

9:228

5:212 

6:216

总结

Mysql千万数据级分表设计及实现方案(2)附一致性哈希原理解析_第1张图片

    节点和分表key按照统一规则计算出一个哈希值(虚拟值),以相同的对比规则按照大小方式进行排列,增加删除节点总是在某一个范围内进行小部分迁移,从而达到减少数据迁移量的目的。

 2、除哈希取模外,还可通过range进行计算

              range: 0-1亿 table0 ;1亿到2亿 table1; 扩容方便;问题:id必须自增,新用户活跃度高,数据热点问题,新增数据表,数据分布不均。

 

 

 

 

 

 

 

 

你可能感兴趣的:(【DB】)