Redis场景应用一:缓存场景
开始梳理Redis的场景应用,Redis有不同的使用场景,有拿来做缓存的,有直接做数据库的,有拿来实现分布式锁的,还可以拿来做一个轻量级的消息队列。这里先梳理一下最常用的应用场景——缓存。场景的学习也比较清晰,本身有一条显式的技术链。比如提到缓存,可以发散到缓存机制、缓存替换、缓存异常等一连串的问题。
一.场景引入
我们需要明确:系统不同层之间的访问速度不一样,所以我们需要缓存这种东西。而在一个层次化的系统中,缓存一定是一个快速子系统。可以看一下我们的计算机系统不同层次之间的速度:
在计算机系统中,默认两种缓存:
- CPU 里面的末级缓存,即 LLC,用来缓存内存中的数据,避免每次从内存中存取数据;
- 内存中的高速页缓存,即 page cache,用来缓存磁盘中的数据,避免每次从磁盘中存取数据。
所以缓存是为了适应不同层次之间的速度不一样的需求。假如说如果每次 CPU 处理数据时,都要从 ms 级别的慢速磁盘中读取数据,然后再进行处理,那么,CPU 只能等磁盘的数据传输完成。这样一来,高速的 CPU 就被慢速的磁盘拖累了,整个计算机系统的运行速度会变得非常慢。
可以上个直观的对比,第一个图写了cpu的速度是ns级别,而磁盘的速度是ms是级别。两者相差了10^6个数量级。为了让对比效果更强烈点:我们假如cpu对应走了1s, 对应的硬盘大概需要走11.57天。假如cpu对应走了1天,硬盘大概需要走2739.7年。这种对比转换法我也忘记在哪学的了,突然想到了~
同时,缓存还有一个重要的特征:缓存系统的容量大小总是小于后端慢速系统的,我们不可能把所有数据都放在缓存系统中。
对应到互联网应用来说,Redis就是快速子系统,而数据库就是慢速子系统了。所以Redis高效的性能通常可以做数据库存储的缓存,比如说给MySQL当缓存,将MySQL热点数据存储在Redis中。
二.缓存的区分
一般来说,缓存分为服务器端缓存和客户端缓存,服务端缓存很常见,也是经常讨论的,客户端缓存是对服务端进行RPC调用之后,将结果存储在客户端,下次请求相同的数据时就可以直接拿到结果。
对于服务端来说,目前的微服务架构下,每个服务其实都应该缓存一些热点数据来减轻热点数据频繁请求带来的压力,因为微服务也要有一定的互不信任原则,简单来说就是请求先到服务A,再到B,但A做过检查之后,B还会再进行一遍检查。
对于客户端来说,频繁请求的数据就有必要做缓存,具体看场景。下面主要还是讨论服务端的缓存
这是按照服务端和客户端进行区分,按照Redis缓存是否接受写请求,我们可以把它分成只读缓存和读写缓存。
三. 缓存的模式
将Redis放在数据库前端做缓存,业务访问数据时,会先查询Redis,无非也就两种情况:缓存命中和缓存消失,当缓存缺少的时候,还需要面临一个缓存更新的问题。更新的时候又会牵扯到一个面试高频——缓存和数据库一致性的问题。这一部分就先抛个砖,后面几篇再进行整理总结。
使用 Redis 缓存时,我们基本有三个操作:
- 应用读取数据时,需要先读取 Redis;
- 发生缓存缺失时,需要从数据库读取数据;
- 发生缓存缺失时,还需要更新缓存。
不同缓存模式的使用方式会有所不同,Redis的缓存模式一般有四种:
1.旁路缓存
这是最常见的模式,应用服务把缓存当做数据库的旁路,直接和缓存进行交互。
Redis是一个独立的系统软件,当我们部署了Redis实例后,如果应用程序想要使用 Redis 缓存,我们就要在程序中增加相应的缓存操作代码,它只会被动等待客户端发起请求。所以,我们也把 Redis 称为旁路缓存,也就是说,读取缓存、读取数据库和更新缓存的操作都需要在应用程序中来完成。通过在应用程序中加入 Redis 的操作代码,我们可以让应用程序使用Redis缓存数据了。
读操作的流程如下:
写操作的流程如下:
旁路缓存适用读多写少的场景,缺点是可能会出现缓存和数据库双写不一致的问题。
2.读穿透模式
这种模式和旁路缓存模式的区别在于应用服务不再和缓存直接交互,而是直接访问数据服务,数据服务也是缓存中有的话就直接查询缓存,不然就查数据库,那为什么要多这个呢?主要是这样缓存对业务透明,业务代码更简洁,缺点是缓存命中时性能不如旁路缓存,因为多了一次服务间调用
3.写穿透模式
缓存使用这个模式就是同步读写缓存,它优先保证数据可靠性,写请求发给缓存的同时,也会发给后端数据库进行处理,等到缓存和数据库都写完数据,才给客户端返回。这样,即使缓存宕机或发生故障,最新的数据仍然保存在数据库中,这就提供了数据可靠性保证。
4.异步缓存写入模式
同理对应异步读写缓存,这个模式和上面的本质差不多,不同的地方在于这个模式不会立即将数据写入数据库中,这个异步写的操作极大减低请求延迟并减轻数据库的负担,缺点在于放大了数据不一致。如果有人直接从数据库中查询数据,但是更新的数据还没有被写入数据库,这时候查询到的数据就不是最新的数据。
四.总结
-
文章先对Redis最常用的使用场景——缓存,进行了场景引入说明,说明了为什么需要缓存这个东西以及缓存的两个重要特征:
- 缓存是一个快速子系统
- 缓存容量相对来说是有限的
-
然后进行了缓存的区分,只读缓存和读写缓存是后面介绍的三种模式的归总,具体来说:读穿透模式归为只读缓存,后面两种归为读写缓存。
-
读写缓存还提供了同步直写和异步写回这两种模式,同步直写模式侧重于保证数据可靠性,而异步写回模式则侧重于提供低延迟访问,我们要根据实际的业务场景需求来进行选择。
-
这篇的内容主要写缓存的一条主线——缓存的机制,后面再接着写缓存替换、缓存异常等一系列问题。
转载自:https://juejin.cn/post/7230819482011779109