高性能网站规划之缓存更新高性能网站规划之缓存更新

2021-09-28    分类: 网站建设

高性能网站规划之缓存更新高性能网站规划之缓存更新


看到好些人在写更新缓存数据代码时,先删去缓存,然后再更新数据库,而后续的操作会把数据再装载的缓存中。可是,这个是逻辑是差错的。试想,两个并发操作,一个是更新操作,另一个是查询操作,更新操作删去缓存后,查询操作没有射中缓存,先把老数据读出来后放到缓存中,然后更新操作更新了数据库。所以,在缓存中的数据仍是老的数据,导致缓存中的数据是脏的,并且还一贯这样脏下去了。


我不知道为什么这么多人用的都是这个逻辑,当我在微博上发了这个贴往后,我发现好些人给了许多十分凌乱和古怪的方案,所以,我想写这篇文章说一下几个缓存更新的Design Pattern(让我们多一些套路吧)。


这儿,我们先不谈论更新缓存和更新数据这两个事是一个业务的事,或是会有失利的可能,我们先假定更新数据库和更新缓存都能够成功的情况(我们先把成功的代码逻辑先写对)。


更新缓存的的Design Pattern有四种:Cache aside, Read through, Write through, Write behind caching,我们下面逐一来看一下这四种Pattern。


Cache Aside Pattern


这是最常用最常用的pattern了。其具体逻辑如下:


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


射中:运用程序从cache中取数据,取到后回来。


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


留心,我们的更新是先更新数据库,成功后,让缓存失效。那么,这种办法是否能够没有文章前面提到过的那个问题呢?我们能够脑补一下。


一个是查询操作,一个是更新操作的并发,首要,没有了删去cache数据的操作了,而是先更新了数据库中的数据,此时,缓存仍然有用,所以,并发的查询操作拿的是没有更新的数据,可是,更新操作马上让缓存的失效了,后续的查询操作再把数据从数据库中拉出来。而不会像文章开始的那个逻辑发作的问题,后续的查询操作一贯都在取老的数据。


这是标准的design pattern,包含Facebook的论文《Scaling Memcache at Facebook》也运用了这个战略。为什么不是写完数据库后更新缓存?你能够看一下Quora上的这个问答《Why does Facebook use delete to remove the key-value pair in Memcached instead of updating the Memcached during write request to the backend?》,主要是怕两个并发的写操作导致脏数据。


那么,是不是Cache Aside这个就不会有并发问题了?不是的,比方,一个是读操作,可是没有射中缓存,然后就到数据库中取数据,此时来了一个写操作,写完数据库后,让缓存失效,然后,之前的那个读操作再把老的数据放进去,所以,会构成脏数据。


但,这个case理论上会出现,不过,实际上出现的概率可能十分低,由于这个条件需求发作在读缓存时缓存失效,并且并发着有一个写操作。而实际上数据库的写操作会比读操作慢得多,并且还要锁表,而读操作必需在写操作跋涉入数据库操作,而又要晚于写操作更新缓存,一切的这些条件都具有的概率根柢并不大。


所以,这也就是Quora上的那个答案里说的,要么通过2PC或是Paxos协议保证一致性,要么就是拼命的下降并发时脏数据的概率,而Facebook运用了这个下降概率的玩法,由于2PC太慢,而Paxos太凌乱。当然,最好仍是为缓存设置上过期时间。


Read/Write Through Pattern


我们能够看到,在上面的Cache Aside套路中,我们的运用代码需求维护两个数据存储,一个是缓存(Cache),一个是数据库(Repository)。所以,运用程序比较烦琐。而Read/Write Through套路是把更新数据库(Repository)的操作由缓存自己代理了,所以,关于运用层来说,就简略许多了。能够理解为,运用认为后端就是一个单一的存储,而存储自己维护自己的Cache。


Read Through


Read Through 套路就是在查询操作中更新缓存,也就是说,当缓存失效的时分(过期或LRU换出),Cache Aside是由调用方担任把数据加载入缓存,而Read Through则用缓存效能自己来加载,然后对运用方是透明的。


Write Through


Write Through 套路和Read Through相仿,不过是在更新数据时发作。当有数据更新的时分,假定没有射中缓存,直接更新数据库,然后回来。假定射中了缓存,则更新缓存,然后再由Cache自己更新数据库(这是一个同步操作)


下图自来Wikipedia的Cache词条。其间的Memory你能够理解为就是我们比方里的数据库。


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。


在wikipedia上有一张write back的流程图,根柢逻辑如下:


再多烦琐一些


1)上面讲的这些Design Pattern,其实并不是软件架构里的mysql数据库和memcache/redis的更新战略,这些东西都是核算机体系结构里的规划,比方CPU的缓存,硬盘文件体系中的缓存,硬盘上的缓存,数据库中的缓存。根柢上来说,这些缓存更新的规划办法都是十分老古董的,并且历经长时间检测的战略,所以这也就是,工程学上所谓的Best Practice,遵从就好了。


2)有时分,我们觉得能做微观的体系架构的人一定是很有经历的,其实,微观体系架构中的许多规划都来源于这些微观的东西。比方,云核算中的许多虚拟化技术的原理,和传统的虚拟内存不是很像么?Unix下的那些I/O模型,也扩展到了架构里的同步异步的模型,还有Unix创造的管道不就是数据流式核算架构吗?TCP的好些规划也用在不同体系间的通讯中,细心看看这些微观层面,你会发现有许多规划都十分精妙……所以,请容许我在这儿放句观点鲜明的话——假定你要做好架构,首要你得把核算机体系结构以及许多老古董的根底技术吃透了。


3)在软件开发或规划中,我十分主张在之前先去参看一下已有的规划和思路,看看相应的guideline,best practice或design pattern,吃透了已有的这些东西,再挑选是否要从头创造轮子。千万不要貌同实异地,想当然的做软件规划。


4)上面,我们没有考虑缓存(Cache)和耐久层(Repository)的整体业务的问题。比方,更新Cache成功,更新数据库失利了怎样吗?或是反过来。关于这个事,假定你需求强一致性,你需求运用“两阶段提交协议”——prepare, commit/rollback,比方Java 7 的XAResource,还有MySQL 5.7的 XA Transaction,有些cache也支撑XA,比方EhCache。当然,XA这样的强一致性的玩法会导致功用下降,关于分布式的业务的相关论题,你能够看看《分布式体系的业务处理》一文。


文章标签:网站建设|网站制作|网页设计|网站建设源码_创新互联

网页题目:高性能网站规划之缓存更新高性能网站规划之缓存更新
网址分享:https://www.cdcxhl.com/news/128810.html

成都网站建设公司_创新互联,为您提供品牌网站建设软件开发网站制作微信小程序网站建设网站导航

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联

成都app开发公司