共计 2007 个字符,预计需要花费 6 分钟才能阅读完成。
面试开始
小伙子你好,看你简历上写到了 MySQL 和 Redis。明天咱们就围绕他们两个开展吧。Redis 和 MySQL 是后端开发中举重若轻的重要角色。理论开发中二者也基本上如影随行,为了进步性能和响应,Redis 经常寄存热点数据,MySQL 寄存所有数据,保证数据长久化。所以 Redis 能够说是 MySQL 的一部分数据。
那么问题来了,当 MySQL 中的长久化数据产生扭转,如何告诉 Redis 呢?也即如何保障缓存和数据库数据的双写一致性呢?
面试官您好,咱们在开发中采取的计划是:先更新数据库,而后删除相应缓存,直到下次申请缓存发现没有数据,再从 MySQL 中读取,同时将数据更新到 Redis。
那为什么采纳删除缓存而不是更新缓存呢?
如下图所示,如果采取更新缓存的形式,可能 呈现申请 A 先于申请 B 产生,更新缓存应该比申请 B 更新缓存早才对,然而因为网络等起因,B 却比 A 更早更新了缓存,这就导致了脏数据 。
其次,如果你是一个写数据库场景比拟多,而读数据场景比拟少的业务需要,采纳更新缓存的计划就会 导致数据压根还没被读取过,但缓存已被频繁的更新,节约性能。
那先删除缓存,再更新数据库会不会有什么问题?
如下图所示,申请 A 进行写操作,删除缓存,申请 B 查问发现缓存不存在,就去数据库查问失去旧值,之后将旧值写入缓存,此时申请 A 再将新值写入数据库。
这种状况就会导致 数据不统一 的情景呈现。而且,如果不采纳给缓存设置过期工夫策略,该缓存数据永远都是脏数据。
好的,刚刚说的计划的确在并发环境中都会有问题。那你们采纳先更新数据库,再删除缓存,这种计划肯定不会呈现并发问题吗?
答案是 不肯定,也可能会呈现并发问题 。如下图所示,
当步骤 Step3 的更新数据库操作比步骤 Step2 的读取数据库操作耗时更短,就有可能使得步骤 Step4 先于步骤 Step5,此时缓存中的就是脏数据。但个别状况下 数据库的读操作的速度是远快于写操作的(此点从 MySQL 的并发读写量就可看出,雷同硬件配置下并发读的效率是并发写的数倍)。
因而,如果你想实现根底的缓存和数据库双写统一的逻辑,那么在大多数状况下,在不想做过多设计、减少太大工作量的状况下,请
先更新数据库,再删除缓存!
先更新数据库,再删除缓存,除了你刚刚说得问题,还会有别的问题吗?
如果MySQL 采纳了读写拆散架构,当申请 A 更新数据在 master 库上并删除了缓存,但此时数据库主从同步还未实现。申请 B 查问缓存产生 Cache miss 之后从 slave 库上读取到的还是旧值,此时也会造成数据不统一。
你刚刚说到先更新数据库,再删除缓存也有可能造成数据不统一,怎么解决呢?
采纳 延时双删 。如下图所示,申请 A 更新数据库之后,为避免删除缓存后行产生于申请 B 的将缓存写入旧值,能够通过将申请 A 更新完数据库之后休眠一会(例如 100ms,200ms,依据理论业务场景拟定),再删除缓存,这样根本能保障缓存中寄存的不会是脏数据。主从架构也是这个原理,就是申请 A 在更新 master 之后不必立刻删除缓存,通过 延时双删保障主从同步曾经实现,最初删除缓存数据。
但你这种计划,申请 A 休眠一段时间的话,可能会影响到接口的 RT,升高零碎的吞吐量,如何解决呢?
这里比拟优雅的计划是通过 异步 实现。即开启一个线程池,在申请 A 的时候开启一个独自的线程,异步的休眠一段时间而后执行缓存删除。当然也能够通过将缓存中相应的 key 扔到音讯队列,通过 MQ 异步删除,但仅为了异步删除缓存就多加了一层音讯队列,可能会造成零碎设计更加简单,并且会带来别的问题。
后面始终有提到删除缓存,如果删除缓存失败了怎么办呢?
再加一个 重试机制,保障删除缓存胜利。
如果我肯定要数据库和缓存数据一致性怎么办?
没有方法做到相对的一致性,这是由 CAP 实践决定的,缓存零碎实用的场景就是非强一致性的场景,所以它属于 CAP 中的 AP。
CAP 实践是分布式系统中的经典实践,即一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。
依据 BASE(Basically Available,Soft State 和 Eventually Consistent)实践,缓存和数据库只能做到数据的 最终一致性。
面试完结
工夫也不早了,明天就到这里吧,看进去小伙子对这块把握的比拟深刻。咱们公司就短少你这种人才,要不当初就签把 Offer 签了吧。
这个时候你必定欲绝还迎,一手接 Offer 一边摆摆手:不行不行,深圳马那边也急着等我给回复呢,催了我好几天了。
面试官一听,payroll 组何在,加价!
小结
应用缓存并不是一个很简略的事件,尤其在须要缓存与数据库放弃强统一的场景,才晓得让数据库数据和缓存数据放弃一致性是一门很浅近的学识。
从远古的硬件缓存,操作系统缓存开始,缓存就是一门独特的学识。这个问题也被业界探讨了十分久,争执至今也无果,因为其实这是一个衡量的问题。
我是少侠露飞,爱技术,爱分享。