
一、故事背景
故事背景机房在华南/华北各一套 Java Dubbo架构,需要同步的数据的组件包含:Redis ,Mysql 。
- 业务特性1:Mysql 访问量较少,正常的情况下并发10都不到。
- 业务特性2:跨机房同步并不是系统所有业务,而是核心业务之一 【特殊业务场景】 。
- 业务特性3:【特殊业务】数据从Mysql 同步到Redis ,高峰访问5W~8WQPS 存储/查询 数据压力都在Redis ,晚上定时再同步到Mysql ,读多、写少。
- 业务特性4:系统业务操作数据都存储在【华南机房】,而【华北机房】用户只会读取数据,和一些【Redis计数】,不存在Mysql写数据。
- 业务特性5:华南、华北机房只能通过外网连接,没有专线。
二、方案
-
A) 方案1: Mysql,Redis直接做跨机房集群,简单省事。
Mysq分析: Mysql读写数据量小,业务特性 数据更新频率低,采用主从从的方式来实现还是可以,但是节点之间的线程同步需要监控,避免同步线程出问题,或者慢、延时带来数据不一致的问题 (做到及时发现及时预案)。
Redis分析: Redis存储数据量比较大,系统【各个业务场景】都有使用,当前占用Redis内存高达到100多G。
问题1: 做跨机房集群,同步数据量大。很可能延时带来各种数据不一致问题(毕竟是外网 很多不可预测问题)。
问题2:多场景数据存储在redis,存储较臃肿,如果【华北】使用量过大、一旦内存占满 导致同步延迟,严重的话还可能导致redis宕机,一旦redis宕机也影响整体业务运行,包括【华南】业务系统。
所以Redis跨机房集群存在的问题太大了,当前业务场景不是太好。如果Redis存储的业务数据量比较小,并能接受跨机房网络带来的延时 还是可以的,简单省事。 -
B)方案2:Mysql 做跨机房主从从,Redis 华南、华北个一套,通过HTTP通知同步数据,保证Redis数据最终一致性。
Redis分析: 由于Redis的数据都是从Mysql拉取的,只要Mysql同步到位,HTTP通知到位。Redis拉取数据就没问题。
所以HTTP一定要使用同步方式,当用户触发同步请求,返回成功才算结束。当然也失去了些用户体验,毕竟有时候由于网络问题触发不成功,得用户重试。
三、方案落地(方案2)

- 1、Mysql跨机房同步数据
- 2、触发查询订单信息。
- 3、查询结果存储到Redis中。
- 4、HTTP通知【华北机房】。
- 5、【华北机房】查询订单信息。
- 6、【华北机房】把结果存储到Redis.
四、总结
-
1、机房之间同步有一定延时,只能达到最终一致性。
-
2、如网络波动,造成跨机房调用缓慢,或失败,严重可能要触发多次重试 才能达到效果。用户体验不友好。
-
3、分布式架构环境下,如果性能要求极致 可以使用【本地缓存】,但通知【华北机房】后 需要通知每个节点去Redis拉取最新的数据到【本地缓存】,可以通过Zookeeper的发布订阅【Watcher】功能。保证每个节点去Redis拉取最新的数据到本地内存。但是有个问题,你很难监控、保证所有节点 【Watcher】同步到本地内存一定是没有问题的。
-
4、目前系统使用【ZK Watcher】没出现过问题,但是风险还是存在的。节点多的情况下一旦某台机器本地缓存同步有问题,排查问题是相当困难。
-
5、数据库跨机房同步一定要监控到,避免同步出现问题 没及时修复 造成巨大损失。
网友评论