DB + 缓存设计

前言概括:

        在满足实时性的条件下,不存在两者完全保存一致的方案,只有最终一致性方案。

 图解说明:

  • 时序图,描述请求的先后调用顺序;
  • 红色的线是请求A,黑色的线是请求B;
  • 红色的文字,是MySQL和Redis最终不一致的数据;
  • 数据是从10更新为11。

1.先写MySQL,再写Redis

请求A、B都是先写MySQL,然后再写Redis,在高并发情况下,如果请求A在写Redis出现卡顿,请求B已经依次完成数据的更新,就会出现图中问题。

不过这里有个前提,就是对于读请求,先去读Redis,如果没有,再去读DB,但是读请求不会再回写Redis。也就是说,读请求不会更新Redis。 

2.先写MySQL,再删除Redis

针对这种情况, 第一次查询,请求B查询的数据是10,但是MySQL的数据是11,只存在这一次不一致的情况,对于不是强一致性要求的业务,可以容忍

当请求B进行第二次查询时,因为没有命中Redis,会重新查一次DB,然后再回写到Redis。

3.先写MySQL,通过Binlog,异步更新Redis

此方案,会保证MySQL和Redis的最终一致性,但是如果中途请求B需要查询数据,如果缓存无数据,就直接查DB;如果缓存有数据,查询的数据也会存在不一致的情况。

所以这个方案,是实现最终一致性的终极解决方案,但是不能保证实时性。 

4.讨论方案比较

(1)先写MySQL,再写Redis

  • 对于并发量、一致性要求不高的项目,很多就是这么用的;
  • 当Redis瞬间不可用的情况,需要报警出来,然后线下处理。

(2)先写MySQL,再删除Redis

  • 比较推荐这种方式,删除Redis如果失败,可以再多重试几次,否则报警出来;
  • 这种方案,是实时性中最好的方案,在一些高并发场景中,推荐使用。

(3)先写MySQL,通过Binlog,异步更新Redis

  • 对于异地容灾、数据汇总、建议用这种方式,比如binlog + kafka,数据的一致性也可以达到秒级;
  • 纯粹的高并发场景,不建议用这种方案,比如抢购、秒杀等。

5.个人结论

  1. 实时一致性方案:采用“先写MySQL,再删除Redis的策略”,这种情况虽然也会存在两者不一致,但是需要满足的条件有点苛刻,所以是满足实时性条件下,能尽量满足一致性的最优解。
  2. 最终一致性方案:采用“先写MySQL,通过Binlog,异步更新Redis”,可以通过Binlog,结合消息队列异步更新Redis,是最终一致性的最优解。

猜你喜欢

转载自blog.csdn.net/m0_60252632/article/details/127085077
DB
今日推荐