电商分布式系统数据库缓存一致性方案分享!

没有一项技术是完美的,任何一项技术都存在驳论。CAP 理论也告诉我们,没有完美无缺!所以缓存一致性问题,分布式架构一致性问题,缓存与数据库不一致问题等都没有完美的解决方案。只有最适合自己业务的解决方案!

参考我前面的那篇文章《电商系统高并发场景中的缓存 DB 数据一致性问题!》所提出的问题。总结下来,用一张图来说明缓存和数据库一致性问题!

640

解决这类问题主要有 4 种方案。参考国外的大厂的做法,Cache Aside Pattern(缓存旁路模式)、Read through Pattern(缓存通读模式)、Write through Pattern(缓存通写模式)、Write behind caching Pattern(写后缓存模式)。这 4 种模式网上都有对应的论文,至于国内的采用延时双删策略等都是在这种基础上的一种演变。

Cache Aside Pattern 缓存旁路模式

缓存旁路模式说白了就是“先更新数据库,再删缓存”这种套路。

简单的解释一下这种策略。

  • 失效:应用程序先从 cache 取数据,没有得到,则从数据库中取数据,成功后,放到缓存中。

  • 命中:应用程序从 cache 中取数据,取到后返回。

  • 更新:先把数据存到数据库中,成功后,再让缓存失效。

640

640

说一下 Facebook 就是采用的这种策略。

你说的这种不就是上面的第三种情况吗?如果发生更新数据库成功,删除缓存失败呢?是不是还会有数据不一致问题。

另外并发情况呢?一个请求A做查询操作,一个请求B做更新操作。那么一定有下面的情形产生:

请求A去查缓存时,缓存刚好失效。所以 A 去查数据库,得到一个值;请求B将新值写入数据库,请求B删除缓存,请求A将查到的旧值写入缓存。

上面两个情况产生后,就会发生数据不一致问题吧。

是的,Facebook 也知道这个问题。但这个 case 理论上会出现,不过,实际上出现的概率可能非常低,因为这个条件需要发生在读缓存时缓存失效,而且并发着有一个写操作。而实际上数据库的写操作会比读操作慢得多,而且还要锁表,而读操作必需在写操作前进入数据库操作,而又要晚于写操作更新缓存,所有的这些条件都具备的概率基本并不大。

所以,这也就是 Quora (参考文末链接)上的那个答案里说的,要么通过 2PC 或是 Paxos 协议保证一致性,要么就是拼命的降低并发时脏数据的概率,而 Facebook 使用了这个降低概率的玩法,因为 2PC 太慢,而 Paxos 太复杂。当然,最好还是为缓存设置上过期时间。

640

总结一下处理流程如下:

  • 更新数据库数据

  • 缓存因为种种问题删除失败

  • 将需要删除的key发送至消息队列

  • 自己消费消息,获得需要删除的key

  • 继续重试删除操作,直到成功

上图虽然可以解决这类问题,但是需要借助消息队列等中间件,太复杂了。改动也太大了,本来概率就小,对于一些一致性要求不是特别高的就更没必要了。

还有一个方案就是借助阿里的 canal 中间件,启动一个订阅程序去订阅数据库的 binlog,获得需要操作的数据。

640

整个流程总结如下:

  • 更新数据库数据

  • 数据库会将操作信息写入 binlog 日志当中

  • 订阅程序提取出所需要的数据以及 key

  • 另起一段非业务代码,获得该信息

  • 尝试删除缓存操作,发现删除失败

  • 将这些信息发送至消息队列

  • 重新从消息队列中获得该数据,重试操作

这样的操作同样是操作太复杂,对于 Facebook 等巨头来说得不偿失。尤其是对于一些新闻类的,少几个阅读量,评论数量,点赞数量的影响不大。

Read through Pattern 缓存通读模式

通过上面的 Cache Aside 模式可以看出,我们的应用代码需要维护两个数据,一个是缓存(Cache),一个是数据库(Repository)。所以,应用程序比较啰嗦。而 Read/Write Through 模式就是把更新数据库(Repository)的操作由缓存自己代理了,所以,对于应用层来说,就简单很多了。可以理解为,应用认为后端就是一个单一的存储,而存储自己维护自己的 Cache。

Read Through 套路就是在查询操作中更新缓存,也就是说,当缓存失效的时候(过期或LRU换出),Cache Aside 是由调用方负责把数据加载入缓存,而 Read Through 则用缓存服务自己来加载,从而对应用方是透明的。

Write through Pattern 缓存通写模式

Write Through 套路和Read Through相仿,不过是在更新数据时发生。当有数据更新的时候,如果没有命中缓存,直接更新数据库,然后返回。如果命中了缓存,则更新缓存,然后再由 Cache 自己更新数据库。

640

Read/Write Through Pattern 策略可以用上面这张图来表示。下面我们在通过一个场景来理解他们。

设想一个场景,老师在黑板上写字,全班在下面一起看,老师想要擦除,但是有人表示自己还没看完,于是老师等待大家看完才擦除黑板。

对于这样的情况就是Read-Write Pattern,线程读取实例状态的时候,实例的状态不会改变,而会使状态变化的只有对线程的写入。

这个模式就是将读和写区分开来进行处理,读之前需要获取读的锁,写的时候需要获取写的锁。读取的时候有多个线程同时读取没有关系,但是有人读取的时候不能进行写操作!

一般来说,进行共享互斥会导致程序性能变差,但是我们将写入的共享互斥和读取的共享互斥分开考虑就会提高程序的性能。

Write behind caching Pattern 写后缓存模式

Write Behind 又叫 Write Back。一些了解Linux操作系统内核的同学对write back应该非常熟悉,这不就是Linux文件系统的Page Cache的算法吗?是的,你看基础这玩意全都是相通的。所以,基础很重要,大道至简。

Write Back套路,一句说就是,在更新数据的时候,只更新缓存,不更新数据库,而我们的缓存会异步地批量更新数据库。这个设计的好处就是让数据的I/O操作飞快无比(因为直接操作内存嘛 ),因为异步,write backg还可以合并对同一个数据的多次操作,所以性能的提高是相当可观的。

但是,其带来的问题是,数据不是强一致性的,而且可能会丢失(我们知道Unix/Linux非正常关机会导致数据丢失,就是因为这个事)。在软件设计上,我们基本上不可能做出一个没有缺陷的设计,就像算法设计中的时间换空间,空间换时间一个道理,有时候,强一致性和高性能,高可用和高性性是有冲突的。软件设计从来都是取舍Trade-Off。

另外,Write Back实现逻辑比较复杂,因为他需要track有哪数据是被更新了的,需要刷到持久层上。操作系统的write back会在仅当这个cache需要失效的时候,才会被真正持久起来,比如,内存不够了,或是进程退出了等情况,这又叫lazy write。

Write Behind Caching Pattern 的处理流程图如下:

640

最后,还是用上面的一句话来总结一下。在软件设计上,我们基本上不可能做出一个没有缺陷的设计,就像算法设计中的时间换空间,空间换时间一个道理,有时候,强一致性和高性能,高可用和高性性是有冲突的。软件设计从来都是取舍Trade-Off。

如果非要保证强一致性,那就采用 2PC、3PC 或是 Paxos 协议保证一致性。

640

最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加QQ1群:135430763(2000人群已满),QQ2群:454796847,QQ3群:187424846。QQ群进群密码:xttblog,想加微信群的朋友,可以微信搜索:xmtxtt,备注:“xttblog”,添加助理微信拉你进群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作可添加助理微信进行沟通!

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如今的大数据技术应用场景,对实时性的要求已经越来越高。作为新一代大数据流处理框架,由于非常好的实时性,Flink独树一帜,在近些年引起了业内极大的兴趣和关注。Flink能够提供毫秒级别的延迟,同时保证了数据处理的低延迟、高吞吐和结果的正确性,还提供了丰富的时间类型和窗口计算、Exactly-once 语义支持,另外还可以进行状态管理,并提供了CEP(复杂事件处理)的支持。Flink在实时分析领域的优势,使得越来越多的公司开始将实时项目向Flink迁移,其社区也在快速发展壮大。目前,Flink已经成为各大公司实时领域的发力重点,特别是国内以阿里为代表的一众大厂,都在全力投入,不少公司为Flink社区贡献了大量源码。如今Flink已被很多人认为是大数据实时处理的方向和未来,很多公司也都在招聘和储备了解掌握Flink的人才。本教程将Flink理论与电商数据分析项目实战并重,对Flink基础理论知识做了系统的梳理和阐述,并通过电商用户行为分析的具体项目用多个指标进行了实战演练。为有志于增加大数据项目经验、扩展流式处理框架知识的工程师提供了学习方式。二、教程内容和目标本教程主要分为两部分:第一部分,主要是Flink基础理论的讲解,涉及到各种重要概念、原理和API的用法,并且会有大量的示例代码实现;第二部分,以电商作为业务应用场景,以Flink作为分析框架,介绍一个电商用户行为分析项目的开发实战。通过理论和实际的紧密结合,可以使学员对Flink有充分的认识和理解,在项目实战中对Flink和流式处理应用的场景、以及电商分析业务领域有更深刻的认识;并且通过对流处理原理的学习和与批处理架构的对比,可以对大数据处理架构有更全面的了解,为日后成长为架构师打下基础。三、谁适合学1、有一定的 Java、Scala 基础,希望了解新的大数据方向的编程人员2、有 Java、Scala 开发经验,了解大数据相关知识,希望增加项目经验的开发人员3、有较好的大数据基础,希望掌握Flink及流式处理框架的求职人员

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值