一、背景
我们公司的用户分布在全球,因为考虑到产品性能和国内安全防护的特殊情况,所以服务端代码分别部署在中、欧、美三个区域的服务器上,同时,也部署了一台用于对全球账号、设备进行唯一验证和管理的全球服务器。
因为各个区域有部分数据表或缓存数据是需要事先在管理后台配置,且大多数据在各个区域一致,因此考虑在全球服务器进行统一配置后直接同步到各个区域服务器。
二、数据同步目标
1. 全球服务器指定数据发生增、删、改时,操作需要同步到中欧美三个区域对应的服务器;
2. 部分数据需要根据数据所属区域分别同步到指定的区域服务器;
3. 新部署服务器后,可以在全球服务器操作一键同步所有配置数据,需要分区域的数据也要区分区域后全部同步;
4. 区域服务器包括web服务器、文件云存储管理服务器、p2p服务器、rpc服务器,web服务器需要同步的数据存储在Mysql数据库,其他服务器需要同步的数据主要存储在redis缓存中;
5. 数据同步实时性要求较高,项目上线后,真实需要在1分钟以内完成数据同步。
ps:项目整体服务架构不在本文讨论范围内,我们其实也在摸索中学习进步,如果有高人不小心看到本篇博客,对架构这部分有经验热心指导的话,还请留言告知,可以加好友学习请教,谢谢。
三、方案思考
遇到这个需求后,查阅了网上各路大神的博客,没有遇到雷同的经验和方案,于是又到技术群请教,本来没多少有效可执行的方案头绪,结果在几个热心大神的启示下,打开了思路,最终得到一个比较有效可执行的方案。
1. 从Mysql层考虑
遇到数据同步问题,大多数人第一反应都是Mysql主从同步,不太了解的朋友可以参考:
https://www.cnblogs.com/zhoujie/p/mysql1.html
https://blog.csdn.net/weixin_41909810/article/details/82939966
如果是同步Mysql部分数据库或部分数据表,可以参考:
https://www.2cto.com/database/201708/674665.html
https://www.csdn.net/gather_2d/MtTaEg5sODY1MS1ibG9n.html
还有朋友推荐考虑使用Mysql的触发器进行部分数据同步,也有一篇文章参考:
https://blog.csdn.net/forever_chm/article/details/86239814
最后没有采用直接配置Mysql数据库同步的方案,原因如下:
(1)因为我没有在实际项目中对mysql进行过这类操作,所以担心后期对数据库造成性能影响;
(2)项目中部分数据表数据不能完全同步到各个区域,需要对数据所属区域进行区分后再同步;
(3)部分数据需要同步至文件云存储、rpc、p2p服务器的缓存数据中,直接操作Mysql不行。
ps:如果只是同步全球数据库的部分表到各个区域数据库,使用Mysql主从同步部分表的操作应该没毛病。
2. 从Redis层考虑
Redis也有数据同步功能,操作参考:
https://blog.csdn.net/ligh_sqh/article/details/79383667
Redis同步指定key到其他库参考:
https://www.cnblogs.com/egrep/p/10084247.html
最后也没有采用Redis数据同步的方式,原因是全球服务器缓存应用和区域完全不同,区域服务器有专属当前区域操作的业务Redis缓存数据,所以如果这样做的话细节问题就太多了。
3. 从消息队列服务考虑
还有朋友建议使用消息队列服务。全球服务器作为生产者,区域服务器作为消费者,在全球服务器操作指定数据后,加入操作内容及数据到队列,消息队列服务配置好需要进行消费的区域服务器接口,实现数据生产 => 消费过程。
这个方案思路让我眼前一新,花了一天思路整理细节逻辑,得到一个绝对可落地的方案,大体如下:
(1)全球服务器根据数据操作类型(增、删、改)以及同步对象的区别(不同类型的区域服务器),对数据进行处理,然后加入Redis数据同步队列;
(2)区域服务器根据自己的数据需求,增加一个数据同步的消费接口,消费成功响应1000,消费失败响应失败数据;
(3)全球服务器增加一个消费Redis数据同步队列的服务,服务中区分同步服务器对象类型,分别调用不同服务器的同步数据消费接口,并且检测同步响应结果,可能存网络原因,如果同步失败,重新进行同步,并增加redis计数器,同一条同步数据超过3次同步失败,加入到数据同步失败日志中,并记录数据同步响应错误结果。
ps:本来有考虑单独开一个消息队列服务,但因为一条数据会同步给多个服务器的情况,就只好在全球服务器中通过代码处理数据再同步至多个服务器。
四、实际落地方案
上文中的方案3是全球数据同步至各区域不同服务器的主要落地方案,但如果所有区域数据库或缓存都通过全球服务器去主动同步,那项目逐渐增大后,性能问题和潜在的架构复杂度也成指数上涨,所以全球到区域的数据同步,要做分层处理,如下:
1. 全球配置数据通过上文方案3同步到区域主服务器(主数据库 / 主Redis);
2. 区域再通过主数据库或主Redis做主从同步,为二级数据库和Redis同步数据。
这样下来,全球服务器数据同步只需要调用对应区域主服务器消费接口就行,至于区域内部的数据同步,就在各自区域内进行操作,和全球服务器没关系。
以上的方案已经在实际项目中操作完成,效果还不错,如果有朋友感兴趣,想了解具体细节,欢迎留言讨论。
--------------------- 原文:https://blog.csdn.net/createNo_1/article/details/94594558