目录

  • 数据库读写分离主从库数据同步延时问题
  • 数据库系统架构发展
  • 主备架构
  • 主从架构
  • 主从延时解决办法
  • 方案1:数据同步写方案(不建议)
  • 方案2:选择性强制读主库
  • 方案3:中间件选择路由
  • Redis缓存路由大法(推荐)
  • 总结


数据库读写分离主从库数据同步延时问题

数据库采用主从架构,数据读写分离,数据查询走的是从库。数据写入都是直接操作主库,后续再同步到从库。

由于数据库同步存在延时,这就导致数据同步的这段时间,主从数据将会不一致,从库无法查询到最新的数据。

如果你之前的数据库系统架构是单库或者主备结构,当你第一次转到数据读写分离架构,这个坑大概率也会踩到。

为了方便理解,下面首先了解一下数据库系统架构,最后再来看下如何解决主从同步延时的导致数据不一致。


数据库系统架构发展

主备架构

业务发展的前期,数据访问量小,这时我们可以直接采用单库的架构

redis 主从延迟监控 redis主从延迟怎么解决_java


不过我们一般不使用的上面的架构,因为存在单点的问题。若数据库出现故障,这段期间业务将会不可用。我们除了等待重启,其他没什么解决办法。所以我们会增加一个备库,实时同步主库的数据

redis 主从延迟监控 redis主从延迟怎么解决_java_02


一旦主库出了故障,通过人工的方式,手动的将主机踢下线,将备机改为主机来继续提供服务。

这种架构,部署维护简单,业务开发也无需任何改造。

不过缺点也很明显,备库只有在主库有问题的时候才会被启用,存在一定的资源浪费的情况。

主从架构

随着业务发展,请求量不断变大,数据量也不断变大,业务变得更加复杂,很快数据将会到达瓶颈。

由于大多数业务都是读多写少,所以数据库读的性能最容易成为系统瓶颈。

这时候我们可以提高读的性能,这时我们的可以采用的方案,增加从实例,主从同步,数据读写分离

redis 主从延迟监控 redis主从延迟怎么解决_redis 主从延迟监控_03


可以看到这个架构与主备没什么区别,主要区别在于主从架构下,从库与主库一样,时刻需要干活,主库提供写服务,从库只提供读服务。

如果后续读的压力还是太大,我们还可以增加从库的数量,水平扩充读的能力。

虽然主从架构帮我们解决读的瓶颈,但是由于主从之间需要数据同步,天然就存在一定延时。在这延时窗口期内,从库的读只能读到一个旧数据,这也是上面案例问题的真正的原因。

如果业务对于数据一致性要求不高,可以不做处理,如果业务对于数据一致性有要求,接下来探讨有什么办法可以优化。


主从延时解决办法

方案1:数据同步写方案(不建议)

主从数据同步方案,一般默认都是采用的异步方式同步给备库。我们可以将其修改为同步方案,主从同步完成,主库上的写才能返回。

redis 主从延迟监控 redis主从延迟怎么解决_redis_04

流程

  1. 业务系统发起写操作,数据写主库
  2. 写请求需要等待主从同步完成才能返回
  3. 数据读从库,主从同步完成就能读到最新数据

这种方案,只需要修改数据库之间同步配置即可,业务层无需修改,相对简单。不过,由于主库写需要等待主从完成,写请求的时延将会增加,吞吐量将会降低。这一点对于现在在线业务,可能无法接受。

方案2:选择性强制读主库

对于需要强一致的场景,我们可以将其的读请求都操作主库,这样读写都在主库,就没有不一致的情况。

redis 主从延迟监控 redis主从延迟怎么解决_java_05


这种方案业务层需要改造一下,将其强制性读主,相对改造难度较低。不过这种方案相对于浪费了另一个数据库,增加主库的压力。

方案3:中间件选择路由

这种方案需要使用一个中间件,所有数据库操作都先发到中间件,由中间件再分发到相应的数据库。

redis 主从延迟监控 redis主从延迟怎么解决_数据库_06


流程如下

  1. 写请求,中间件将会发到主库,同时记录一下此时写请求的 key(操作表加主键等)
  2. 读请求,如果此时 key 存在,将会路由到主库
  3. 一定时间后(经验值),中间件认为主从同步完成,删除这个 key,后续读将会读从库

这种方案,可以保持数据读写的一致。但是系统架构增加了一个中间件,整体复杂度变高,业务开发也变得复杂,学习成本也比较高。

Redis缓存路由大法(推荐)

这种方案与中间件的方案流程比较类似,不过改造成本相对较低,不需要增加任何中间件。

redis 主从延迟监控 redis主从延迟怎么解决_mysql_07


流程如下:

  1. 写请求发往主库,同时缓存记录操作的 key,缓存的失效时间至少设置为主从的延时的时间;
  2. 读请求首先判断缓存是否存在
    若存在,代表刚发生过写操作,读请求操作主库
    若不存在,代表近期没发生写操作,读请求操作从库

这种方案相对中间件的方案成本较低,但是此时又引入一个缓存组件,所有读写之间就又多了一步缓存操作。


总结

引入主从架构,数据读写分离,目的是为了解决业务快速发展,请求量变大,并发量变大,从而引发的数据库的读瓶颈。

不过当引入新一个架构解决问题时,势必会带来另外一个问题,数据库读写分离之后,主从延迟从而导致数据不一致的情况。,

为了解决主从延迟,数据不一致的情况,我们可以采用以下这几种方案:

  1. 数据库同步写方案
  2. 选择性强制读主
  3. 中间件选择路由法
  4. 缓存路由大法

上面的方案都有各自的优缺点,我们需要根据自己的业务情况,选择相应的解决方案。