使用binlog缓存异步化

42 篇文章 2 订阅
27 篇文章 0 订阅

在高并发的系统中关于缓存的重要性不言而喻,缓存在项目当中大量使用,扛住了大部分的查询流量,但也有很多点需要注意,最为典型的例子就是数据一致性问题,缓存击穿问题,缓存高可用问题等等。这次需要解决的问题是一个秒杀场景的高并发问题。

关于缓存一致性问题

缓存一致性就是说DB的数据与缓存的数据保持一致,理论上同一瞬间去变更两个值是最理想的,访问缓存跟DB是一致的,但是在分布式的情况下,无论如何操作,更新DB与缓存是存在间隙的。并且在结合实际情况下的多线程环境,那问题将更加复杂,我们可以简单回顾下这几种场景下不一致的原因。

  • 同时更新缓存的策略

  • 先更新DB再更新缓存
    此方案线程T1更新数据库数据D1->D2,还没更新缓存,线程T2更新数据D2->D3,由于线程T2可能比较快,直接更新缓存为D3,此时运行“缓慢”的T1才更新缓存为D2。结果为DB的数据为D3,缓存的数据为D2。

  • 先更新缓存再更新DB
    同样的道理,线程T1更新完缓存还没更新DB,线程T2很快更新完缓存立马T2更新DB为D2,这个时候T1才更新DB为D1,数据库为D1,缓存为D2。而且这里还有个比较严重的问题是如何保证缓存与DB的事务一致性,本地事务执行失败如何解决。

  • 删缓存的策略

  • 先删缓存再更新DB
    T1删除缓存,还没更新DB,T2查询出来老数据塞到缓存,此时T1更新DB, DB与缓存不一致.

  • 先更新DB再删除缓存
    此方案为网上较多的一种比较好的方案,但是仍然存在数据不一致的情况,例如T1先读取数据D1, T2更新DB为D1->D2,T2删除缓存,T1更新刷新缓存塞D1,此时DB的数据为D2,缓存的数据为D1。
    只是综合来看,先更新DB再删缓存这样的数据不一致的概率会低很多,因为一般读请求的耗时更短,只有再T1的耗时大于写入的T2,并且T1要直接查询到DB的情况下才会发生。

关于秒杀的问题

秒杀是在瞬间极高的流量,无论是查询或则更新库存的流量都存在瞬间峰值,我们当然引入了缓存这种中间件支撑整个系统,redis是比较流行的一种内存数据库,我们一般用来做缓存中间件,也是采用了先更新DB再删除缓存的方案,这种方案是尽量保证实时数据一致性,因此性能开销并不低,考虑到实际情况库存业务上游大流量感知的更多是关心的是有或则无的状态,理论上,返回给一个布尔值就能支撑业务。秒杀情况下,DB在频繁更新库存的时候也在频繁的删除缓存,这个时候用户也在频繁的查询是否还有库存,这些并发的查询流量都形成了缓存穿透。
在这里插入图片描述
在秒杀的极端情况下,DB的压力陡然增加,因此需要另辟蹊径找到缓存更高效的方案.

binlog与缓存

在我印象中binlog主要是用来主从同步与高可用数据恢复等等操作的用途,主要是给DBA用的,其实还可以应用在一些其他的场景,缓存就是其中的一个场景,可以用来异步做很多解耦的事情。其实这种方案并不多,可能因为其异步的特性,存在延迟,但是这个问题我通过其他方式规避了。
[图2]

  • 其带来的好处:
  1. 作为高并发系统,不用在同步失效缓存,进一步降低接口rt
  2. 应用解耦,不强依赖redis。
  3. 分散在业务代码各处的更新缓存操作可以收敛在一个地方,业务代码更加简洁。
  4. 缓存不再失效,有效解决高并发查询流量缓存击穿问题。
  • 但是其仍然存在一些问题:
  1. 强依赖binlog与消息中间件的可用性与延迟.
  2. 数据存在延迟性与不一致的概率增加。

根据CAP与BASE理论与实际业务,保证最终一致性(顺序消息)是最佳的方案,上游仅仅需要感知库存不足的情况下的库存,因此这里作业特殊逻辑,在库存不足的时候立即更新缓存为DB的最新值,但是这样仍然存在一个问题,延迟的消息可能仍然将老的值覆盖进来,这就需要丢弃,因此每条库存记录都存在一个递增版本号。每次消息的消费都会判断当前缓存的版本号与消息的版本号的大小,如果小于丢弃即可,但是仍然存在一个问题由于在判断版本大小之后和在更新缓存之前,这个“缝隙”代码做了一些可能存在高耗时的操作,因此再更新缓存之前可能当前消息仍存在“是延迟消息”的风险,因此需要塞之前做二次判断,尽量保证数据一致性。
在这里插入图片描述

发布问题

涉及到消息的监听,建消息和应用的发布先后顺序需要考虑。

  1. 先发代码,再建立消息,落在发布机器上 所有扣减的库存的地方缓存不会失效,消息监听可能落在其他的未发布的集群,不会刷新缓存,所以有问题。
  2. 如果先发消息、再发布代码,因为发布代码是一个灰度发布的过程,依旧存在问题1的问题。
  3. 可以通过加开关的方式,先发布所有代码,再建消息,再开开关,全部失效缓存的地方不失效,但这样存在比较大的风险,因为每一步都是全流量验证.
  4. 分两次发布,先发布代码让监听消息的地方都去刷新缓存。
    第一次发布:扣库存逻辑不变,都会失效缓存,老机器监听消息没问题,新机器监听无非多刷新一次缓存,没问题。
    第二次发布:扣库存逻辑不会失效缓存,新老机器监听消息已经会刷新缓存,没问题。

看了此篇文章是不是感觉收获蛮大

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值