Redis缓存的工作机制

技术博客 (223) 2023-12-13 18:01:01

Redis:缓存的工作机制

  • Redis缓存的工作机制
  • 缓存的特征
  • Redis缓存处理请求
  • Redis作为旁路缓存
  • Redis中缓存的类型
    • 只读缓存
    • 读写缓存
  • 参考文献

Redis缓存的工作机制

Redis具有高性能的数据存取特性,广泛的应用于缓存场景,在提升业务应用响应速度的同时,也避免了将数据查询的压力发送到了数据库。Redis用作缓存的普遍性和其在应用中的钟涛作用,我们需要了解Redis为什么能够用作缓存一级其具体的工作机制。

缓存的特征

无论是计算机系统还是具体的应用,其架构都是分层的。系统中的不同层之间访问速度是不一样的,所以将一些经常被访问的数据放到缓存中就可以加快其访问速度。

以计算机系统为例,下图展现了计算机系统中的三层存储结构以及其容量和访问性能。CPU、内存、磁盘的访问速度差别很大。如果每次CPU处理数据都要从磁盘中读取,那么磁盘就会拖累CPU的计算,影响整个计算机的运行速度。
Redis缓存的工作机制 (https://mushiming.com/) 技术博客 第1张
计算机中默认有两种缓存:

  • CPU中的末级缓存,LLC,用于缓存内存中的数据从而避免每次从内存中读取数据;
  • 内存中的缓存,page cache,用来缓存磁盘中的数据,避免每次从磁盘中读取数据。
    Redis缓存的工作机制 (https://mushiming.com/) 技术博客 第2张
    从上图中可以看出,访问速度上来看:LLC>page cache>磁盘,从存储容量来看:磁盘>page cache>内存。所以可以得出缓存的两个特征:
  • 特征一:在一个层次化系统中,缓存是一个快速的子系统,可以避免每次从慢速子系统中存取数据;
  • 特征二:缓存系统的容量大小是小于后端慢速系统的,不可能将所有的数据都放在缓存中。

因为缓存的容量是有限的,所以缓存中的数据需要按一定规则淘汰出去,写回后端系统,而新的数据又要从后端系统中读取进来,写入缓存。我们可以学习下缓存是如何处理请求的,当业务应用在访问Redis缓存中的数据时,数据不一定内存,因此其处理方式也是不同的。

Redis缓存处理请求

Redis用作缓存时,会把Redis部署在数据库的前端,当业务应用在访问数据时。先查询Redis中是否保存了相应的数据,然后在根据数据是否在缓存中分为以下两种情况:

  • 缓存命中:Redis中有相应数据,直接读取Redis,性能非常快;
  • 缓存缺失:Redis中没有相应的数据,一旦缓存缺失,为了让后续请求能够从缓存中读取数据,就需要把缺失的数据写入Redis中,即为缓存更新的过程;

通常我们的应用是一个web应用,用户的请求发送到Tomcat,Tomcat负责处理业务逻辑,如果需要访问数据就需要从MySQL中读写数据。Redis在用作缓存时有三个基本操作:

  • 应用读取数据时,需要先读取Redis;
  • 发生缓存缺失时,需要先从数据库读取数据;
  • 发生缓存缺失时,还需要更新缓存;

Redis缓存的工作机制 (https://mushiming.com/) 技术博客 第3张

Redis作为旁路缓存

Redis是一个独立的系统软件,和业务应用程序是两个软件。在Redis部署完之后,如果程序中想要执行Redis缓存就需要增加相应的缓存操作代码,读取缓存、读取数据、更新缓存等操作都需要在应用程序中完成,所以称为旁路缓存。

平时在开发程序时,我们是没有专门在代码中显式地创建LLC或page cache的实例的,也没有显式调用过它们的GET接口。这是因为,我们在构建计算机硬件系统时,已经把LLC和page cache放在了应用程序的数据访问路径上,应用程序访问数据时直接就能用上缓存。

而使用Redis用作缓存时就需要增加三方面的代码:

  • 应用程序读取数据时,需要调用Redis的GET操作接口进行查询;
  • 缓存缺失,应用程序需要和数据库连接,从数据库中读取数据;
  • 当缓存中的数据需要更新时,需要在应用程序中显式调用SET操作接口将更新的数据写入缓存;

为了使用缓存,Web应用程序需要有一个表示缓存系统的实例对象redisCache,还需要主动调用Redis的GET接口,并且要处理缓存命中和缓存缺失时的逻辑,例如在缓存缺失时,需要更新缓存。

不过,除了从Redis缓存中查询、读取数据以外,应用程序还可能会对数据进行修改,这时,我们既可以在缓存中修改,也可以在后端数据库中进行修改,我们该怎么选择呢?

Redis中缓存的类型

Redis缓存的两种类型:只读缓存和读写缓存。只读缓存能加速读请求,而读写缓存可以同时加速读写请求。

只读缓存

当Redis用作只读缓存时,应用要读取数据的话,会先调用Redis GET接口,查询数据是否存在。而所有的数据写请求,会直接发往后端的数据库,在数据库中增删改。对于删改的数据来说,如果Redis已经缓存了相应的数据,应用需要把这些缓存的数据删除,Redis中就没有这些数据了。

当应用再次读取这些数据时,会发生缓存缺失,应用会把这些数据从数据库中读出来,并写到缓存中。这样一来,这些数据后续再被读取时,就可以直接从缓存中获取了,能起到加速访问的效果。

举个例子:如果业务嘤嘤需要修改数据A,如果缓存中有数据A,应用会现在数据库中修改A,再将Redis中的A删除。等到应用需要读取数据A时就会发生缓存丢失,应用从数据库中读取A,并且写入Redis以便后续请求能够从缓存中直接读取。
Redis缓存的工作机制 (https://mushiming.com/) 技术博客 第4张

读写缓存

对于读写缓存来说,除了读请求会发送到缓存进行处理(直接在缓存中查询数据是否存在),所有的写请求也会发送到缓存,在缓存中直接对数据进行增删改操作。此时,得益于Redis的高性能访问特性,数据的增删改操作可以在缓存中快速完成,处理结果也会快速返回给业务应用,这就可以提升业务应用的响应速度。

在使用读写缓存时,最新的数据是在Redis中,而Redis是内存数据库,一旦出现掉电或宕机,内存中的数据就会丢失。这也就是说,应用的最新数据可能会丢失,给应用业务带来风险。

所以根据业务应用对数据可靠性和缓存性能的不同要求,我们会有同步直写和异步写回两种策略。

  • **同步直写:**写请求发送给缓存的同时也会发给后端数据库进行处理,等到缓存和数据库都写完数据之后才返回给客户端,保证数据库中存储的是最新的数据,提供了数据可靠性的保证。同步直写会降低缓存的访问性能。这是因为缓存中处理写请求的速度是很快的,而数据库处理写请求的速度较慢。即使缓存很快地处理了写请求,也需要等待数据库处理完所有的写请求,才能给应用返回结果,这就增加了缓存的响应延迟。
  • 异步写回:优先考虑了响应延迟,所有写请求都先在缓存中处理。等到这些增改的数据要被从缓存中淘汰出来时,缓存将它们写回后端数据库。

Redis缓存的工作机制 (https://mushiming.com/) 技术博客 第5张
关于是选择只读缓存,还是读写缓存,主要看我们对写请求是否有加速的需求。

  • 如果需要对写请求进行加速,我们选择读写缓存;
  • 如果写请求很少,或者是只需要提升读请求的响应速度的话,我们选择只读缓存。

举个例子,在商品大促的场景中,商品的库存信息会一直被修改。如果每次修改都需到数据库中处理,就会拖慢整个应用,此时,我们通常会选择读写缓存的模式。而在短视频App的场景中,虽然视频的属性有很多,但是,一般确定后,修改并不频繁,此时,在数据库中进行修改对缓存影响不大,所以只读缓存模式是一个合适的选择。

参考文献

1、极客时间-Redis核心技术与实战

THE END

发表回复