缓存一定要用redis吗

2021-02-10  本文已影响0人  gabz

缓存一定要用redis吗

「缓存」,写程序的肯定都用过。

使用缓存的目的只有2个:提升速度、减轻数据库压力。

使用缓存虽然也很简单的,但还是有很多细节可以推敲。

经典的缓存更新策略

我就先摆一些经典的缓存模式,其实我们有时候都不知道它是一个模式的时候,都已经在用了。

一般有以下几种:

名字看上去很专业,但其实原理都比较简单,大家有时间可以去网上搜一下,我很多也是搜回来的,下面我只挑里面重点讲扼要。

Cache Aside

Cache-Aside-Design-Pattern-Flow-Diagram-e1470471723210.png Updating-Data-using-the-Cache-Aside-Pattern-Flow-Diagram-1-e1470471761402.png

上面就是整个更新缓存的流程图,重点我们可以看下面的图更新缓存的方式:

缓存失效了后,等下次Application再请求数据的时候,就会回到第一张图,如此循环。

其实这个就是我们经常使用的更新缓存逻辑,但这里存在一个高并发情况下的问题。

然而高并发情况触发条件比较苛刻,所以如果对缓存再加上一个适当的TTL(Time To Live,过期时间),缓存数据的准确性要求不高,那问题就不大。

Read/Write Through

Read/Write Through 更新逻辑如下所示

dcc0b5c52ce691ac9fbd591f0d5a4a82_1440w.jpg

咋看其实跟上面Cache Aside没什么区别,但架构上多了一个Cache的服务,Cache服务层充当写入、更新、读取缓存的服务。

整体数据流就是:应用 > Cache 服务 > 数据库。所以跟Cache Aside最大的区别在于:

Write Behind

Write Behind 更新逻辑如下所示

293f4fd60aa7cc24c7b233d2f543ba21_1440w.jpg

截取《缓存更新的套路》的一段话解释

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

但是,其带来的问题是,数据不是强一致性的,而且可能会丢失,但软件设计没有完美,都是权衡取舍。

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

如果中间件服务挂掉呢

其实可以看出,上面几个缓存使用策略,逻辑都是 Cache Aside 基础上强化改造。那我们回到 Cache Aside 的逻辑看,除了上面说的 “高并发” 问题,其实还有其他问题。

回忆一下,在Cache Aside的模式中,我们在更新缓存:

image-20210125194734959.png

一般来说,程序部署标准都是用各种中间件,比如一个程序用了缓存,就用redis;数据库,就用mysql。那么一个完整的程序,就有程序应用实例、redis、数据库,当三个服务都正常时,就会提供正常响应,但如果redis或者数据库访问异常呢。

redis 异常

如果redis异常的话,一般程序会有2种表现:

数据库异常

数据库异常本身就是比较大的故障,整体程序应该大部分都不能用。

但有时偶尔的网络抖动导致访问失败也是有可能的,那如果刚好缓存被设置为失效,又请求数据库失败的这种情况下,就会返回失败。

这种情况下,如果redis缓存还有旧数据,就可以暂时返回给用户。

真的要用中间件吗

理论上来说,redis和数据库作为中间件而言,一般都是具有较高可用性,比如腾讯云上的redis就达到99.5%。

image-20210210091338201.png

但中间件终归是一种共享服务,除了本身的稳定性,还需要依赖网络的稳定性,相互请求也需要带宽。

回到「缓存」这个主题上来,要增加使用缓存的稳定性,还有一个可以考虑的点,就是是否真的需要使用redis。因为少一个外部依赖点,程序性能相对稳定性可控。

假如程序里面的缓存符合以下特性:

符合以上特性,其实建议还是使用本地缓存,缺点就是增加了代码复杂度,要考虑过期、线程安全等;但对应也是有措施,可以用一些框架来缓解代码复杂度的问题。

本地缓存另外一个问题就是缓存更新,因为在分布式系统下,同一个应用的缓存就散落到各个实例上,如何主动统一刷新多态进程实例的缓存也是一个问题。

上一篇 下一篇

猜你喜欢

热点阅读