当前位置: 首页 > news >正文

[架构师之路] 数据库拆分 系列(下)


从好友中心开始,聊「多对多」类业务数据库水平切分架构实践
https://mp.weixin.qq.com/s?src=11&timestamp=1513062109&ver=569&signature=kFm0O5Lwn2WcP9T3OQWem11HGXHdAPVeblezxZ8wVEWfRAcQq*ANJxfoh077cI4WR5wMQqP1gZIcUh6*pw0LAQq10eE0j61uM6I95V1xIIdotNza8XHJv*zLukZi2gK8&new=1

本文将以「好友中心」为例,介绍「多对多」类业务,随着数据量的逐步增大,数据库性能显著降低,数据库水平切分相关的架构实践。


一、什么是多对多关系
所谓的「多对多」,来自数据库设计中的「实体-关系」ER模型,用来描述实体之间的关联关系,一个学生可以选修多个课程,一个课程可以被多个学生选修,这里学生与课程时间的关系,就是多对多关系。


二、好友中心业务分析
好友关系主要分为两类, 弱好友关系与强好友关系,两类都有典型的互联网产品应用。
弱好友关系的建立,不需要双方彼此同意
用户A关注用户B,不需要用户B同意,此时用户A与用户B为弱好友关系,对A而言,暂且理解为“关注”;
用户B关注用户A,也不需要用户A同意,此时用户A与用户B也为弱好友关系,对A而言,暂且理解为“粉丝”;
微博粉丝是一个典型的弱好友关系应用。

强好友关系的建立,需要好友关系双方彼此同意
用户A请求添加用户B为好友,用户B同意,此时用户A与用户B则互为强好友关系,即A是B的好友,B也是A的好友。
QQ好友是一个典型的强好友关系应用。

好友中心是一个典型的多对多业务,一个用户可以添加多个好友,也可以被多个好友添加,其典型架构为:

1) friend-service:好友中心服务,对调用者提供友好的RPC接口
2) db:对好友数据进行存储


三、弱好友关系-元数据简版实现
通过弱好友关系业务分析,很容易了解到,其核心元数据为:
guanzhu(uid, guanzhu_uid);
fensi(uid, fensi_uid);
其中:
guanzhu 表,用户记录 uid 所有关注用户 guanzhu_uid
fensi 表,用来记录 uid 所有粉丝用户 fensi_uid
需要强调的是,一条弱关系的产生,会产生两条记录,一条关注记录,一条粉丝记录
例如:用户A(uid=1)关注了用户B(uid=2),A多关注了一个用户,B多了一个粉丝,于是:
guanzhu表要插入{1, 2}这一条记录,1关注了2
fensi表要插入{2, 1}这一条记录,2粉了1

如何查询一个用户关注了谁呢?
回答:在guanzhu的uid上建立索引:
select * from guanzhu where uid=1;
即可得到结果,1关注了2。
如何查询一个用户粉了谁呢?
回答:在fensi的uid上建立索引:
select * from fensi where uid=2;
即可得到结果,2粉了1。


四、强好友关系-元数据实现一
通过强好友关系业务分析,很容易了解到,其核心元数据为:
friend(uid1, uid2);
其中:
uid1,强好友关系中一方的uid
uid2,强好友关系中另一方的uid

uid=1的用户添加了uid=2的用户,双方都同意加彼此为好友,这个强好友关系,在数据库中应该插入记录{1, 2}还是记录{2,1 }呢?
回答:都可以,为了避免歧义,可以人为约定,插入记录时uid1的值必须小于uid2。
例如:有uid=1,2,3三个用户,他们互为强好友关系,那边数据库中可能是这样的三条记录
{1, 2} {2, 3} {1,3 }
如何查询一个用户的好友呢?
回答:假设要查询uid=2的所有好友,只需在uid1和uid2上建立索引,然后:
select * from friend where uid1=2
union
select * from friend where uid2=2
即可得到结果。
作业:为何不使用这样的SQL语句呢?
select * from friend uid1=2 or uid2=2
供大家思考。


五、强好友关系-元数据实现二
强好友关系是弱好友关系的一个特例,A和B必须互为关注关系(也可以说,同时互为粉丝关系),即也可以使用关注表和粉丝表来实现:
guanzhu(uid, guanzhu_uid);
fensi(uid, fensi_uid);
例如:用户 A(uid=1) 和用户 B(uid=2) 为强好友关系,即相互关注:
用户 A(uid=1) 关注了用户 B(uid=2),A多关注了一个用户,B多了一个粉丝,于是:
guanzhu 表要插入{1, 2}这一条记录
fensi 表要插入{2, 1}这一条记录
同时,用户B(uid=2)也关注了用户A(uid=1),B多关注了一个用户,A多了一个粉丝,于是:
guanzhu 表要插入{2, 1}这一条记录
fensi 表要插入{1, 2}这一条记录


六、数据冗余是实现多对多关系水平切分的常用实践
对于强好友关系的两类实现:
friend(uid1, uid2)表
数据冗余 guanzhu 表与 fensi 表(后文称正表T1与反表T2)
在数据量小时,看似无差异,但数据量大时,数据冗余的优势就体现出来了:
friend 表,数据量大时,如果使用uid1来分库,那么uid2上的查询就需要遍历多库
         正表 T1 与反表 T2 通过数据冗余来实现好友关系,{1,2}{2,1}分别存在于两表中,故两个表都使用 uid 来分库,均只需要进行一次查询,就能找到对应的关注与粉丝,而不需要多个库扫描
数据冗余,是多对多关系,在数据量大时,数据水平切分的常用实践。


七、如何进行数据冗余
接下来的问题转化为,好友中心服务如何来进行数据冗余,常见有三种方法。
方法一:服务同步冗余
顾名思义,由好友中心服务同步写冗余数据,如上图1-4流程:

1. 业务方调用服务,新增数据
2. 服务先插入T1数据
3. 服务再插入T2数据
4. 服务返回业务方新增数据成功
优点:
1. 不复杂,服务层由单次写,变两次写
2. 数据一致性相对较高(因为双写成功才返回)
缺点:
1. 请求的处理时间增加(要插入次,时间加倍)
2. 数据仍可能不一致,例如第二步写入T1完成后服务重启,则数据不会写入T2

如果系统对处理时间比较敏感,引出常用的第二种方案
方法二:服务异步冗余
数据的双写并不再由好友中心服务来完成,服务层异步发出一个消息,通过消息总线发送给一个专门的数据复制服务来写入冗余数据,如上图1-6流程:

1. 业务方调用服务,新增数据
2. 服务先插入T1数据
3. 服务向消息总线发送一个异步消息(发出即可,不用等返回,通常很快就能完成)
4. 服务返回业务方新增数据成功
5. 消息总线将消息投递给数据同步中心
6. 数据同步中心插入T2数据
优点:
请求处理时间短(只插入1次)
缺点:
1. 系统的复杂性增加了,多引入了一个组件(消息总线)和一个服务(专用的数据复制服务)
2. 因为返回业务线数据插入成功时,数据还不一定插入到T2中,因此数据有一个不一致时间窗口(这个窗口很短,最终是一致的)
3. 在消息总线丢失消息时,冗余表数据会不一致

如果想解除“数据冗余”对系统的耦合,引出常用的第三种方案
方法三:线下异步冗余
数据的双写不再由好友中心服务来完成,而是由线下的一个服务或者任务来完成,如上图1-6流程:

1. 业务方调用服务,新增数据
2. 服务先插入T1数据
3. 服务返回业务方新增数据成功
4. 数据会被写入到数据库的log中
5. 线下服务或者任务读取数据库的log
6. 线下服务或者任务插入T2数据    
优点:
1. 数据双写与业务完全解耦
2. 请求处理时间短(只插入1次)
缺点:
1. 返回业务线数据插入成功时,数据还不一定插入到T2中,因此数据有一个不一致时间窗口(这个窗口很短,最终是一致的)
2. 数据的一致性依赖于线下服务或者任务的可靠性
上述三种方案各有优缺点,可以结合实际情况选取。
数据冗余固然能够解决多对多关系的数据库水平切分问题,但又带来了新的问题,如何保证正表T1与反表T2的数据一致性呢?


八、如何保证数据的一致性
上一节的讨论可以看到,不管哪种方案, 因为两步操作不能保证原子性,总有出现数据不一致的可能,高吞吐分布式事务是业内尚未解决的难题,此时的架构优化方向,并不是完全保证数据的一致,而是尽早的发现不一致,并修复不一致。

最终一致性,是高吞吐互联网业务一致性的常用实践。更具体的,保证数据最终一致性的方案有三种。
方法一:线下扫面正反冗余表全部数据

如上图所示,线下启动一个离线的扫描工具,不停的比对正表T1和反表T2,如果发现数据不一致,就进行补偿修复。
优点:
1. 比较简单,开发代价小
2. 线上服务无需修改,修复工具与线上服务解耦
缺点:
1. 扫描效率低,会扫描大量的“已经能够保证一致”的数据
2. 由于扫描的数据量大, 扫描一轮的时间比较长,即数据如果不一致,不一致的时间窗口比较长
有没有只扫描“可能存在不一致可能性”的数据,而不是每次扫描全部数据,以提高效率的优化方法呢?

方法二:线下扫描增量数据
每次只扫描增量的日志数据,就能够极大提高效率,缩短数据不一致的时间窗口,如上图流程所示:

1. 写入正表T1
2. 第一步成功后,写入日志log1
3. 写入反表T2
4. 第二步成功后,写入日志log2
当然, 我们还是需要一个离线的扫描工具,不停的比对日志log1和日志log2,如果发现数据不一致,就进行补偿修复
优点:
1. 虽比方法一复杂,但仍然是比较简单的
2. 数据扫描效率高,只扫描增量数据
缺点:
1. 线上服务略有修改(代价不高,多写了2条日志)
2. 虽然比方法一更实时,但 时效性还是不高,不一致窗口取决于扫描的周期

有没有实时检测一致性并进行修复的方法呢?
    方法三:实时线上「消息对」检测
这次不是写日志了,而是向消息总线发送消息,如上图流程所示:

1. 写入正表T1
2. 第一步成功后,发送消息msg1
3. 写入反表T2
4. 第二步成功后,发送消息msg2
这次不是需要一个周期扫描的离线工具了,而是 一个实时订阅消息的服务不停的收消息
假设正常情况下,msg1和msg2的接收时间应该在3s以内,如果检测服务在收到msg1后没有收到msg2,就尝试检测数据的一致性,不一致时进行补偿修复。
优点:
1. 效率高
2. 实时性高
缺点:
1. 方案比较复杂,上线引入了消息总线这个组件
2. 线下多了一个订阅总线的检测服务
however,技术方案本身就是一个投入产出比的折衷,可以根据业务对一致性的需求程度决定使用哪一种方法。


九、总结
文字较多,希望尽量记住如下几点:
* 好友业务是一个典型的多对多关系,又分为强好友与弱好友 。
* 数据冗余是一个常见的多对多业务数据水平切分实践。

* 冗余数据的常见方案有三种:
* 服务同步冗余
* 服务异步冗余
* 线下异步冗余

* 数据冗余会带来一致性问题,高吞吐互联网业务, 要想完全保证事务一致性很难,常见的实践是最终一致性。
* 最终一致性的常见实践是,尽快找到不一致,并修复数据,常见方案有三种。
* 线下全量扫描法
* 线下增量扫描法
* 线上实时检测法



多key业务,数据库水平切分架构一次搞定
http://mp.weixin.qq.com/s?src=11&timestamp=1513062109&ver=569&signature=zJdPCWywod1RFFBRDijOPJU1cl4cM7dO9qvXNxwocCGYftvwMrOkUgwd0WmFSYmCm1nuWPBsjPdNJWnBN2V5*HgLqsfiR5toBgleR7om8H976YDXVneA*tjQYEO0lMFR&new=1


前言
数据库水平切分是一个很有意思的话题,不同业务类型,数据库水平切分的方法不同。
本篇将以“订单中心”为例,介绍“多key”类业务,随着数据量的逐步增大,数据库性能显著降低,数据库水平切分相关的架构实践。

一、什么是“多key”类业务
所谓的“多key”,是指一条元数据中,有多个属性上存在前台在线查询需求
订单中心业务分析
订单中心是一个非常常见的“多key”业务,主要提供订单的查询与修改的服务,其核心元数据为:
Order(oid, buyer_uid, seller_uid, time, money, detail…);
其中:
1)oid为订单ID,主键
2)buyer_uid为买家uid
3)seller_uid为卖家uid
4)time, money, detail, …等为订单属性
数据库设计上,一般来说在业务初期,单库单表就能够搞定这个需求,典型的架构设计为:

1)order-center:订单中心服务,对调用者提供友好的RPC接口。
2)order-db:对订单进行数据存储。

随着订单量的越来越大,数据库需要进行水平切分, 由于存在多个key上的查询需求,用哪个字段进行切分,成了需要解决的关键技术问题
1)如果用 oid 来切分,buyer_uid 和seller_uid 上的查询则需要遍历多库。
2)如果用buyer_uid 或seller_uid 来切分,其他属性上的查询则需要遍历多库。
总之,很难有一个完全之策,在展开技术方案之前,先一起梳理梳理查询需求。


二、订单中心属性查询需求分析
在进行架构讨论之前,先来对业务进行简要分析,看哪些属性上有查询需求。
前台访问,最典型的有三类需求:
  • 订单实体查询:通过 oid 查询订单实体,90%流量属于这类需求。
  • 用户订单列表查询:通过 buyer_uid 分页查询用户历史订单列表,9%流量属于这类需求。
  • 商家订单列表查询:通过 seller_uid 分页查询商家历史订单列表,1%流量属于这类需求。

前台访问的特点:吞吐量大,服务要求高可用,用户对订单的访问一致性要求高,商家对订单的访问一致性要求相对较低,可以接受一定时间的延时。
后台访问,根据产品、运营需求,访问模式各异:按照时间,架构,商品,详情来进行查询。运营侧的查询基本上是批量分页的查询,由于是内部系统,访问量很低,对可用性的要求不高,对一致性的要求也没这么严格,允许秒级甚至十秒级别的查询延时。
这两类不同的业务需求,应该使用什么样的架构方案来解决呢?


三、前台与后台分离的架构设计
如果前台业务和后台业务公用一批服务和一个数据库,有可能导致,由于后台的“少数几个请求”的“批量查询”的“低效”访问,导致数据库的cpu偶尔瞬时100%,影响前台正常用户的访问(例如,订单查询超时)。

前台与后台访问的查询需求不同,对系统的要求也不一样,故应该两者解耦,实施“前台与后台分离”的架构设计。
前台业务架构不变,站点访问,服务分层,数据库水平切分。
后台业务需求则抽取独立的 web/service/db 来支持,解除系统之间的耦合,对于“业务复杂”“并发量低”“无需高可用”“能接受一定延时”的后台业务:
1) 可以去掉 service 层,在运营后台 web 层通过 dao 直接访问数据层。
2) 可以不需要反向代理,不需要集群冗余。
3) 可以通过 MQ 或者线下异步同步数据,牺牲一些数据的实时性。
4) 可以使用更契合大量数据允许接受更高延时的“索引外置”或者“HIVE”的设计方案。

解决了后台业务的访问需求,问题转化为,前台的oid,buyer_uid,seller_uid如何来进行数据库水平切分呢?
多个维度的查询较为复杂,对于复杂系统设计,可以逐步简化。


四、假设没有seller_uid
订单中心, 假设没有seller_uid 上的查询需求,而只有 oid 和buyer_uid 上的查询需求,就蜕化为一个“1对多”的业务场景,对于“1对多”的业务,水平切分应该使用“基因法”。
再次回顾一下,什么是分库基因?
通过buyer_uid 分库,假设分为16个库,采用buyer_uid %16的方式来进行数据库路由,所谓的模16,其本质是buyer_uid 的最后4个bit决定这行数据落在哪个库上,这4个bit,就是分库基因。
也再次回顾一下,什么是基因法分库?
在订单数据 oid 生成时,oid 末端加入分库基因,让同一个buyer_uid 下的所有订单都含有相同基因,落在同一个分库上。

如上图所示,buyer_uid=666 的用户下了一个订单:
使用 buyer_uid%16 分库,决定这行数据要插入到哪个库中。
分库基因是 buyer_uid 的最后4个 bit,即1010。
在生成订单标识 oid 时,先使用一种分布式 ID 生成算法生成前 60bit(上图中绿色部分)。
将分库基因加入到 oid 的最后4个 bit(上图中粉色部分),拼装成最终64bit的订单 oid(上图中蓝色部分)。
通过这种方法保证,同一个用户下的所有订单oid,都落在同一个库上,oid的最后4个bit都相同,于是:
通过 buyer_uid%16 能够定位到库。
通过 oid%16 也能定位到库。


五、假设没有oid
订单中心, 假设没有 oid 上的查询需求,而只有 buyer_uid 和 seller_uid 上的查询需求,就蜕化为一个“多对多”的业务场景,对于“多对多”的业务,水平切分应该使用“数据冗余法”。

如上图所示:
1. 当有订单生成时,通过 buyer_uid 分库,oid 中融入分库基因,写入 DB-buyer 库。
2. 通过线下异步的方式,通过 binlog+canal,将数据冗余到 DB-seller 库中。
3. buyer 库通过buyer_uid 分库,seller 库通过seller_uid 分库,前者满足 oid 和buyer_uid 的查询需求,后者满足seller_uid 的查询需求。
数据冗余的方法有很多种:
1. 服务同步双写。
2. 服务异步双写。
3. 线下异步双写(上图所示,是线下异步双写)。
不管哪种方案,因为两步操作不能保证原子性,总有出现数据不一致的可能,高吞吐分布式事务是业内尚未解决的难题,此时的架构优化方向,并不是完全保证数据的一致,而是尽早的发现不一致,并修复不一致。
最终一致性,是高吞吐互联网业务一致性的常用实践。保证数据最终一致性的方案有三种:
1. 冗余数据全量定时扫描。
2. 冗余数据增量日志扫描。
3. 冗余数据线上消息实时检测。
这些方案细节在“多对多”业务水平拆分的文章里详细展开分析过,便不再赘述。


六、oid/buyer_uid/seller_uid同时存在
通过上述分析:
如果没有seller_uid ,“多key”业务会蜕化为“1对多”业务,此时应该使用“基因法”分库:使用buyer_uid 分库,在oid中加入分库基因
如果没有oid,“多key”业务会蜕化为“多对多”业务,此时应该使用“数据冗余法”分库:使用buyer_uid 和seller_uid 来分别分库,冗余数据,满足不同属性上的查询需求
如果 oid/buyer_uid/seller_uid 同时存在,可以使用上述两种方案的综合方案,来解决“多key”业务的数据库水平切分难题。


七、总结
复杂难题的解决,都是一个化繁为简,逐步击破的过程。
对于像订单中心一样复杂的“多key”类业务,在数据量较大,需要对数据库进行水平切分时,对于后台需求,采用“前台与后台分离”的架构设计方法:
前台、后台系统web/service/db分离解耦,避免后台低效查询引发前台查询抖动。
采用前台与后台数据冗余的设计方式,分别满足两侧的需求。
采用“外置索引”(例如ES搜索系统)或者“大数据处理”(例如HIVE)来满足后台变态的查询需求。
对于前台需求,化繁为简的设计思路,将“多key”类业务,分解为“1对多”类业务和“多对多”类业务分别解决:
使用“基因法”,解决“1对多”分库需求:使用buyer_uid 分库,在oid中加入分库基因,同时满足oid和buyer_uid 上的查询需求
使用“数据冗余法”,解决“多对多”分库需求:使用buyer_uid 和seller_uid 来分别分库,冗余数据,满足buyer_uid 和seller_uid 上的查询需求
如果oid/buyer_uid/seller_uid同时存在,可以使用上述两种方案的综合方案,来解决“多key”业务的数据库水平切分难题。
数据冗余会带来一致性问题,高吞吐互联网业务,要想完全保证事务一致性很难,常见的实践是最终一致性。



数据库秒级平滑扩容架构方案
https://mp.weixin.qq.com/s?src=3&timestamp=1513077230&ver=1&signature=xqjBIqXRrTSrhO9bVfPMKw*Gg90a6ZTGaG2SA1uH4jM33DCEbZfS2fxc103tKX9k0PEoUCD3h4-Fr3kpZ9MJSKPwM5IQvT5xy2CbhTVd3-3mzy-uNpI5j9-p4Vayg0as794k8*zD96VpBMVGxd*t2-wb49Fg-ZLdBKxX9vGPms4=

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


如上图:服务层配置用户库user对应的数据库实例物理位置为ip(其实是一个内网域名)。
(2)随着数据量的增大,数据要进行水平切分,分库后将数据分布到不同的数据库实例(甚至物理机器)上,以达到降低数据量,增强性能的扩容目的:

如上图:用户库user分布在两个实例上,ip0和ip1,服务层通过用户标识uid取模的方式进行寻库路由,模2余0的访问ip0上的user库,模2余1的访问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;
这样修改是为了保证,拆分后依然能够路由到正确的数据。
(2)reload配置,实例扩容
服务层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)修改配置
(2)reload配置,实例扩容完成
(3)删除冗余数据等收尾工作,数据量收缩完成 

http://www.taodudu.cc/news/show-8458098.html

相关文章:

  • 每周一篇 文献阅读—paper1
  • CentOS 软链接实战记录
  • python 创建软连接_Linux ln命令:在文件之间建立链接(硬链接和软链接)详解版...
  • 软考(20)-TCPDNSTelnetDHCPwindows管理
  • 软考备考之十天通过软件设计师(软考总结)
  • 计算机软重启,软重启、硬重启、重启、重置,这些概念你搞清楚了吗
  • Shell笔记第一天 软链接
  • 天软行业全景画像定期报告(2023-12)报告概要
  • 天软高频时序数据仓库
  • MAC系统下的终端的`简单`美化 | iTerm | zsh | oh-my-zsh
  • gulp的简单使用(MAC OX 系统)
  • 目标检测YOLO实战应用案例100讲-基于无人机图像的玉米漏苗自动检测
  • 【62】二叉搜索树的第k个结点
  • 植树月收尾:31号抢胡杨
  • 《我的南方和北方》朗读演讲配乐伴奏朗诵演出舞台大屏幕背景视频素材
  • 庄忻恬和黎全胜先生共同演绎诗朗诵《声音》,声情并茂
  • 语音识别语音朗诵
  • 计算机发展音频网,计算机如何储存音频
  • 经典优美朗诵背景音乐
  • Python环境利用百度AI语音识别朗诵文章
  • YSDK的巨坑!登录没有回调!
  • 取消/开启——WIN10的选择关机原因提示
  • 技术概念:敏捷开发、持续集成、持续交付和DevOps的定义及关系梳理
  • 把带宽理解为高速公路的两种含义
  • html如何使组件靠右边,如何对齐这些HTML组件?
  • 项目DTO规范
  • 数据治理:对于元数据的理解
  • 这个“云端”的名字起的太大了吧?应该叫“软件管理器”更为贴切。
  • 迄今为止我看到的最贴切的对DOM的解释
  • 分享一个关于面向对象的贴切比喻