贝聊亿级数据库分库分表实践

4,280 阅读6分钟
文章作者:唐璜,贝聊资深JAVA工程师,曾长期就职于网易
方案实施:郑晓滨,贝聊高级JAVA工程师,曾就职于网易

首先说明一下,这是贝聊2016年针对班级动态所实施的一个数据库分库分表方案,经过一年多的验证,证明我们的方案是可行的,因此分享给大家。
一、业务场景
班级动态是贝聊为家长和老师提供的一个核心功能,类似于微信朋友圈、微博、QQ空间等的好友动态功能,是幼儿园家长老师使用频率最高的功能之一。在贝聊,老师和家长都可以在班级里发布动态、评论动态、点赞动态,内容可以包含文字、图片或者视频等内容。目前只要涉及到好友、粉丝之类的APP或者是网站基本都有这个功能,所以这个业务场景大家应该都很熟悉,就不多介绍了,附一张贝聊APP里班级动态的截图:
二、现状(2016年)
贝聊从2013年成立,至2016年,使用贝聊的幼儿园已经达到几万所,班级动态业务涉及的数据也已经达到亿级,且每天以几十万的速度在增长,预计三年左右就能达到数十亿。与此同时,动态的回复和点赞的数量更大,通常是动态量的几倍到十几倍的样子。

而班级动态、评论与点赞三个表,当时跟幼儿园、班级等主业务数据表放在一起,直接存储在阿里云RDS(MySQL数据库)上,虽然有做主从,但未做分库分表处理(这应该是创业公司初期的通病)。

三、存在问题
容量瓶颈: 单机数据库随着数据量和访问量的增长一定会遇到服务瓶颈。
扩展困难: 单机数据库扩展最终需要依赖硬件升级,扩展过程复杂、对业务影响大。
使用成本高: 单机数据库为获得更高的服务能力,依赖特定的高端设备,成本高昂。
可靠性低: 单机数据库的数据集中存储,宕机时直接影响所有数据库数据的访问。
四、目标
优化后,未来三到五年不需要进行大规模的优化。同时,在避免性能问题的基础上,能支撑几亿甚至几十亿的动态。
五、实施方案
1、独立班级动态数据库
从主业务数据库里剥离班级动态相关数据表,独立成库。原因很简单,一是独立出来方便做处理,二是任何一方有问题,都不会影响另一业务的正常运行。
2、切分班级动态数据库的数据
在要支撑几亿甚至几十亿的数据,同时有频繁的插入和查询的业务场景,不进行数据切分肯定是行不通的。

这里说的数据切分是水平切分,水平切分主要目的是为了突破单节点数据库服务器的 I/O 能力限制,解决数据库扩展性问题。水平切分时首先是通过一系列的切分规则将数据分布到不同的DB或table中,再通过相应的DB路由或者table路由规则找到需要查询的具体DB或者table,最后进行相关操作。

以下看看我们的班级动态、评论与点赞三个表:
由此可见,班级动态表、回复表与点赞表都与幼儿园id相关。实际业务场景就是如此,用户必须在其所在的幼儿园下发布动态,也只能查看、回复与点赞所在幼儿园的动态。那么选择幼儿园id字段作为分库与分表的键,不论是拆分、插入、查询都是没问题的。

那么,分多少个库合适,分多少个表合适,根据什么规则分,一旦单表数量再次达到性能瓶颈怎么办?针对这些问题,我们经过了充分的调研讨论,最后决定采用阿里云 DRDS方案来实施。

DRDS(Distributed Relational Database Service,分布式关系型数据库服务 )是阿里巴巴自主研发,致力于解决单机数据库瓶颈而推出的分布式数据库中间件产品。

先看看阿里云官网关于DRDS的产品介绍(这块好像DRDS的软文,阿里云是不是该付我们广告费呢): DRDS 高度兼容 MySQL 协议和语法,支持水平拆分、平滑扩容、弹性扩展、透明读写分离和分布式事务等特性,具备分布式数据库全生命周期的运维管控能力。
DRDS 支持库级拆分、表级拆分和分库分表拆分。拆分键暂时只支持单个字段。
分库键:DRDS 根据分库键的值将数据水平拆分到后端的每一个 RDS 分库里。键值相同的数据,一定会位于同一个 RDS 数据库里。
分表键:每一张逻辑表都可以定义自己的分表键,键值相同的数据,一定会位于同一个 RDS 数据表里。
由于我们在使用阿里云的RDS,同时我们只需要根据单个字段(幼儿园id)拆分,所以我们用阿里云 DRDS作为分库分表方案完全没毛病,对吧?切分方案确定后,丢给阿里搞,少死好多脑细胞,马云也一边偷着乐去了。

根据阿里云DRDS的官方建议:未来2年预估班级动态数据总量 = DRDS建议单表容量 X 分表数量 X 分库数量
3、独立动态业务
重构现有的班级动态模块,并将其独立成一个Dubbo服务组件。代码重构的目标主要有以下几点:
1)保证大部分的SQL语句能够使用分库分表键,避免全表扫描
2)避免使用JOIN语句,使用单表查询替代
3)灵活使用缓存策略减少DB压力
六、效果比较
1、 性能大幅度提升
响应速度提升5至10倍,以当时获取班级动态列表接口为例:
分库分表实施前:响应时间大致为200ms至1500ms级之间。
分库分表实施后:响应时间提升至大致为30ms至300ms之间。
2、 可方便快速进行横向扩容
如果需要扩容,直接按照阿里云DRDS指引,增加新的分库即可。
3、 架构的优化
独立动态业务,通过Dubbo提供服务,对系统进行解耦,让业务具备快速横向扩容能力。
4、后遗症
独立后,暂时没有做分布式事务,在业务中需要避免跨库事务。