即日起在codingBlog上分享您的技术经验即可获得积分,积分可兑换现金哦。

数据库秒级平滑扩容架构方案

微信 架构师之路 10℃ 0评论

一、缘起

1并发量大,流量大的互联网架构,一般来说,数据库上层都有一个服务层,服务层记录了“业务库名”与“数据库实例”的映射关系,通过数据库连接池向数据库路由sql语句以执行:

如上图:服务层配置用户库user对应的数据库实例物理位置为ip(其实是一个内网域名)。

 

2随着数据量的增大,数据要进行水平切分,分库后将数据分布到不同的数据库实例(甚至物理机器)上,以达到降低数据量,增强性能扩容目的:

如上图:用户库user分布在两个实例上,ip0ip1,服务层通过用户标识uid取模的方式进行寻库路由,模20的访问ip0上的user库,模21的访问ip1上的user库。


关于数据库水平切分,垂直切分的更多细节,详见《一分钟掌握数据库垂直拆分 。


3)互联网架构需要保证数据库高可用,常见的一种方式,使用双主同步+keepalived+ip的方式保证数据库的可用性:

如上图:两个相互同步的主库使用相同的虚ip

如上图:当主库挂掉的时候,虚ip自动漂移到另一个主库整个过程对调用方透明,通过这种方式保证数据库的高可用。


关于高可用的更多细节,详见《究竟啥才是互联网架构“高可用”》。

 

4)综合上文的(2)和(3),线上实际的架构,既有水平切分,又有高可用保证,所以实际的数据库架构是这样的:

 

提问:如果数据量持续增大,分2个库性能扛不住了,该怎么办呢?

回答继续水平拆分,拆成更多的库,降低单库数据量,增加库主库实例(机器)数量,提高性能。


最终问题抛出:分成x个库后,随着数据量的增加,要增加到y个库,数据库扩容的过程中,能否平滑,持续对外提供服务,保证服务的可用性,是本文要讨论的问题。

 

二、停服务方案

在讨论平滑方案之前,先简要说明下“x库拆y停服务的方案:

1)站点挂一个公告“为了为广大用户提供更好的服务,本站点/游戏将在今晚00:00-2:00之间升级,届时将不能登录,用户周知”

2停服务

3新建y个库,做好高可用

4数据迁移,重新分布,写一个数据迁移程序,从x个库里导入到y个库里,路由规则由%x升级为%y

5修改服务配置,原来x行配置升级为y

6重启服务,连接新库重新对外提供服务

整个过程中,最耗时的是第四步数据迁移

 

回滚方案

如果数据迁移失败,或者迁移后测试失败,则将配置改回x库,恢复服务,改天再挂公告。

 

方案优点:简单

 

方案缺点

1)停服务,不高可用

2技术同学压力大,所有工作要在规定时间内做完,根据经验,压力越大约容易出错(这一点很致命)

3)如果有问题第一时间没检查出来,启动了服务,运行一段时间后再发现有问题,难以回滚,需要回档,可能会丢失一部分数据

 

有没有更平滑的方案呢?

 

三、秒级、平滑、帅气方案

再次看一眼扩容前的架构,分两个库,假设每个库1亿数据量,如何平滑扩容,增加实例数,降低单库数据量呢?三个简单步骤搞定。

 

1)修改配置

主要修改两处:

a)数据库实例所在的机器做双虚ip,原来%2=0的库是虚ip0,现在增加一个虚ip00%2=1的另一个库同理

b)修改服务的配置(不管是在配置文件里,还是在配置中心),将2个库的数据库配置,改为4个库的数据库配置,修改的时候要注意旧库与辛苦的映射关系

%2=0的库,会变为%4=0%4=2

%2=1的部分,会变为%4=1%4=3

这样修改是为了保证,拆分后依然能够路由到正确的数据

 

2reload配置,实例扩容

服务层reload配置,reload可能是这么几种方式:

a)比较原始的,重启服务,读新的配置文件

b)高级一点的,配置中心给服务发信号,重读配置文件,重新初始化数据库连接池


不管哪种方式,reload之后,数据库的实例扩容就完成了,原来是2个数据库实例提供服务,现在变为4个数据库实例提供服务,这个过程一般可以在秒级完成。

 

整个过程可以逐步重启,对服务的正确性和可用性完全没有影响

a)即使%2寻库和%4寻库同时存在,也不影响数据的正确性,因为此时仍然是双主数据同步的

b)服务reload之前是不对外提供服务的,冗余的服务能够保证高可用

 

完成了实例的扩展,会发现每个数据库的数据量依然没有下降,所以第三个步骤还要做一些收尾工作。

 

3)收尾工作,数据收缩

有这些一些收尾工作

a)把双虚ip修改回单虚ip

b解除旧的双主同步,让成对库的数据不再同步增加

c增加新的双主同步,保证高可用

d删除掉冗余数据,例如:ip0%4=2的数据全部干掉,只为%4=0的数据提供服务啦


这样下来,每个库的数据量就降为原来的一半数据收缩完成

 

四、总结

该帅气方案能够实现n库扩2n库的秒级、平滑扩容,增加数据库服务能力,降低单库一半的数据量,其核心原理是:成倍扩容,避免数据迁移


迁移步骤

1修改配置

2reload配置实例扩容完成

3删除冗余数据等收尾工作,数据量收缩完成

 

希望大伙有收获,好文值得转发

==【完】==

相关阅读:

一分钟掌握数据库垂直拆分

究竟啥才是互联网架构“高可用”

究竟啥才是互联网架构“高并发”

100亿数据1万属性数据架构设计

转载请注明:CodingBlog » 数据库秒级平滑扩容架构方案

喜欢 (0)or分享 (0)
发表我的评论
取消评论

*

表情
(27)个小伙伴在吐槽
  1. 58到家招聘后端开发(java方向),前端fe,测试开发,产品经理。base北京,只要牛逼薪水不限,不加班,地点立水桥南,可以经常和楼主一起讨论技术,欢迎留言推荐自荐。
    58沈剑2017-02-09 11:03 回复
  2. 博主多发发文章 学到不少干货 至于跳槽就算了吧 /呲牙
    勇闯天涯2017-02-09 11:15 回复
  3. 好像没做切换时双主的数据可能存在还没有完全同步的措施/撇嘴
    啊彪2017-02-09 11:16 回复
  4. 哇,这个方案帅炸了,有一点没明白,增加辛苦之后由原来的2变4,此时原来uid 取模之后对应的库的地址会变,如何保证老数据完美迁移呐
    wier2017-02-09 11:20 回复
  5. 不加班?不信……/回头/回头
    A卓2017-02-09 11:21 回复
  6. 一个问题就是这里的模运算其实是需要一点数学知识的,沈大的数学学的不错,我只能理解,却想不到
    候鸟归来的季节2017-02-09 11:27 回复
  7. 要是8变16 就要8主同步吗
    善良的自行车2017-02-09 11:33 回复
  8. 这么好的文章怎能不赞赏
    无眠2017-02-09 11:55 回复
  9. 感谢分享,刚接触您的帖子,太棒了,赶紧拜读其他大作
    圣杰是也2017-02-09 12:32 回复
  10. 1.偶数成倍2-4、4-8、8-16扩容… 2.删除冗余数据…例如2->4,要删除4个节点一半的数据…数据量大要删很久吧?
    Mr Liu2017-02-09 12:52 回复
  11. 完美的方案,方案实施前需要数据库先做高可用,至少有一份冗余数据,扩容的服务器也需要成倍整加
    张雷明2017-02-09 13:16 回复
  12. 这个方案貌似只适合双主同步的架构。这个架构有两个问题,第一个问题这个架构总会有一半的机器是backup,平时并没有对外提供服务,有点浪费;第二个问题,如果是读请求有瓶颈,一主多从读写分离的架构只需要扩从库即可,而不需要再继续分库,而双主就必须继续分库继续配置更多的backup,造成更大的浪费
    Frank2017-02-09 15:48 回复
  13. 沈老师您好,我想问下最后那个收尾阶段删除旧的双主同步后还没有添加新的同步,如果刚好数据库宕掉了是不是会有风险
    luojims2017-02-10 01:01 回复
  14. 这是我的一篇关于分库分表的文章http://www.jianshu.com/p/32b3e91aa22c
    ~小桥~流水~2017-02-10 01:03 回复
  15. 文章很帅。但是在帅气扩容第二步,图像可能有偏差。在没去除双虚拟节点的情况下,%4=0或%4=2都会同时落到两台机器。 再赞牛逼的方案。
    青山绿水2017-02-10 02:06 回复
  16. 老沈,我们公司现在还没有做微服务化,系统间通信用的还是rpc,现在一堆wcf服务快有二三十个了,有啥好的治理方案么?
    zxd2017-02-10 02:09 回复
  17. 好文,一直在关注在看,刚刚在头条上看到有人直接复制过去这篇文章,要不要维权啊
    为为委2017-02-10 14:56 回复
  18. 很好,方案简单实用。同时请问一下,案例子中这个平滑扩容是只做分库没做分表吧?
    sailor2017-02-13 16:37 回复
  19. 这个方案吊炸天,👍👍👍
    sheldon-zhao2017-02-15 11:24 回复
  20. 求问你们双主是怎么实现的?
    贺博@超星2017-02-17 01:55 回复
  21. 很好的方案,不知道沈老师有没有写分库的策略和分库后的业务(上文说的server层)实现呢?id取余分库,那where id in (1,2,3,4,5),就要折成where id in (1,3,5)和where id in (2,4)么?
    昌~Mr.谢2017-02-20 06:29 回复
  22. 两个库分为4个库时,数据是通过双主复制过去的?每个库都是1亿?
    赵晓军2017-02-20 10:47 回复
  23. 对称结构扩容,如果路由规则变成多级规则,是不是减少扩容冗余,只对单节点进行二次扩容。在沈老师方案中想到,双倍扩容,所需服务器和流浪控制不一定均匀,系统流量分摊可以再精细到节点级
    娄娄2017-02-21 23:54 回复
  24. 数据库实例都放一个机器上,不会造成资源竞争么?双主都在一个机子上靠谱么?
    Neal2017-02-23 02:52 回复
  25. 好文,必须打赏,沈大大牛逼
    nq_with_you@java2017-02-25 06:49 回复
  26. 好像没做切换时双主的数据可能存在还没有完全同步的措施。 博主并没有解决这个问题,冒着数据错误的风险。这并不是一个好的解决方案,特别对于金融数据。
    楼飞麒麟lf2017-03-09 15:07 回复
  27. 我们数据库是采用这个策略实现扩容的,但是不会秒级那么简单,因为存量数据需要扩散到新增加的数据库,需要做数据扩散到新增的库中,这个需要一个同步过程,同步OK后,才能执行应用层切换。 这个同步过程需要时间,看具体的数据量。
    大明2017-04-12 10:55 回复