小米以及当前公司分库分表的实践

本文目录:

        介绍什么是分库分表;

        为什么要分库分表;

        怎么做分库分表,小米是如何实现的;如何进行数据迁移。

        分库分表遇到的问题;

        分库分表的下一代解决方案;

介绍什么是分库分表,为什么要分库分表

        介绍分库分表之前,要说下数据库架构的演进过程。最早的数据库是单体应用,和我们的业务系统部署在同一个机器上。随着业务发展,数据库和业务系统分开部署,大量的读请求会触发高频次的随机IO,这在一定程度上影响了写请求,且我们的业务几乎都是读多写少,因此数据库演变成了一主多从(也有多主多从,但常用的还是一主多从)的部署方式,且实现了读写分离。写只写主库,读只读从库。架构类似如下:

        小米之前基于开源KingShard中间件做了一层代理,客户端发起请求后,代理会解析SQL,根据sql类型以及是否有显示指定主库来决定应该把请求发给主库还是从库。如:

   "select /*master*/ *  from table"  显示读主库,默认读从库。

        读写分离一定程度上分摊了高并发请求和检索性能,但如果单库或者单表的数据量过大,其TPS/QPS以及查询能力都会下降。下面是我们现在一个业务系统的几张表,都几十G了。

下面是数据库健康状况监控的例子:

        当单库或者单表的数据量过大时,无论如何进行性能调优(重建索引,优化SQL等,增加单机配置),都无法改变当前的读请求的性能,此时单DB的性能已经达到了瓶颈。如果读写请求频次不高,可以忍一忍。但如果还是读写非常频繁的业务,特别是高并发场景下,基本上整个业务会受到DB的拖累,严重的会导致整个系统崩溃。此时,就要考虑进行分库分表了。

        分库分表的基本思想就是将之前揉在一个机器上的库和表根据某种规则进行拆分,将单表数据分散到多个字库或者多张表上,不同的库表会部署在不同的机器上,从而减轻单个节点的压力。类似下图,单张1000w条的数据表,根据某个规则拆分成10张表:

怎么做分库分表

拆分方式

拆分方式包括两种:垂直拆分和水平拆分

1)垂直拆分

        垂直拆分主要是拆库,根据业务功能区划分,比如在电商系统中订单,商品,库存,履约,风控等业务应该使用独立的数据库。记得在2018年,那时我们后端所有业务的数据表都在一个库中,有个负责拼团的同学在自己代码中引入了一个bug,大概逻辑是遍历所有用户并在每个循环内都执行一次慢查询,用户数量应该有几十万。不出意外,在618的时候,系统崩掉了,导致30分钟都下不了单。导致出现问题的根本原因就是其他业务的慢查询拖垮了DB,从而影响了使用同一个DB的其他业务,尤其是下单,这简直是个灾难。因此,我们痛定思痛,开始进行拆库,各个业务线逐步将数据库拆分出去。

垂直分库

        垂直拆分是和分布式系统相辅相成的,微服务的建立的前提应该就是底层数据源的隔离,否则毫无意义。那么垂直拆分的原则在上面也说了,要根据业务去划分,这个地方倒是不复杂。

2)水平分库分表

        水平拆分包括既分库又分表,也可以不分库只分表,两种方式的目的都是将单张表数据分散到多个分表,每个分表的数量成倍减少,从而减轻了对单表的读写压力。既分库又分表的做法是不仅仅分表,还要根据一定规则分到不同的库中,不同的库可以部署在不同的机器上。相比于只分表不分库的做法,分库分表可以降低单台机器的瓶颈,毕竟单台机器的CPU,内存,磁盘IO,带宽等都是有限的。因此,通常情况下我们都会采用分库分表的做法。

拆分规则

        分库分表该如何去拆分?该采用什么规则将数据平均分散到各个分表上?是不是符合我们实际的业务场景?

目前业界通用的分表规则主要有以下几种:

  1. 按照范围分配
  2. 基于子库数量的哈希取模
  3. 一致性Hash

1、按照范围range分配

思想: 按照某个字段值以及某种规则拆分,每个子表都划分一定范围的数据。可以按照时间或者其他的分片字段。

优点: 基于范围查询或更新速度快,需要的数据可能落在同一张子表中,避免遍历全部子表。比如我们按照年分表,多数请求查询某一年的。

缺点: 有可能造成数据倾斜,数据不均衡。还是拿月份举例吧。对于电商系统,11月份大促期间的订单量要远远大于其他月份。

适用场景: 比较适合于有大量范围查询需求的场景。比如做财务数据统计,完全可以以月或者年进行分割。

2、Hash取模

思想: 选定某个分片字段,对子库(表)数量进行hash取模算出下标,从而决定落到哪一个分片上。比如用户 uid,分了16个库(分库按照序号排列 0~15)。 uid %16 计算出对应分库下标。图片来源于网络:

优点: 数据相对比较均衡,基本上不会造成数据倾斜。

缺点: 最大的缺点就是不容易扩缩容。因为它是hash取模的,基数是子库数量,数量变化之后,需要重新计算下标。这种变化对数据的迁移相对比较麻烦的。

适用场景: 本分片规则是比较常用的规则,也是大家的首选。算法简单,其缺点可以说是瑕不掩瑜。因为我们在分表时可以尽量将字库数量设置多一些。或者可以评估未来几年的数据量。

3、一致性hash

思想: 是对按照实际子库数量hash取模的改进。首先对分片字段hash,随后对2^32除余,从而确保值落到2^32 - 1区间,按照顺时针找到第一个节点就是对应服务器的位置,算法是hash(key)%2^32。下面是网上找到的一个比较容易理解的图:

优点: 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值