Redis与缓存解读

2025-01-11 04:50
文章标签 redis 缓存 解读

本文主要是介绍Redis与缓存解读,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《Redis与缓存解读》文章介绍了Redis作为缓存层的优势和缺点,并分析了六种缓存更新策略,包括超时剔除、先删缓存再更新数据库、旁路缓存、先更新数据库再删缓存、先更新数据库再更新缓存、读写穿透和异步...

缓存

在业务开发中,必然会存在需要频繁访问的数据即热点数据,如果通过访问数据库访问这些数据,由于数据存储在磁盘上,在频繁访问下会进行频繁的IO操作,会导致数据库压力过大,响应速度变慢。

那么我们可以在添加php一层中间缓存层,将热点数据缓存在内存中,在访问数据时我们不在直接查询数据库,而是先访问缓存,如果数据存在(命中),直接返回即可。如果数据不存在(未命中),再访问数据库。

Redis与缓存解读

Redis 将数据存储在内存中,因此可以提供接近于内存的访问速度。所以 redis 天然适合作为缓存层。

缓存并不是万能的,实际上缓存更使用于读密集场景,在写密集场景中由于需要保证缓存于数据库的一致性,在修改缓存时还需要修改数据库,反而加重了后端压力。

缓存优缺点

优点:

  • 降低后端负载
  • 提高读写效率,降低响应时间

缺点:

  • 增加数据一致性成本
  • 增加代码维护成本

缓存更新策略

为了保证缓存数据有效,我们需要更新缓存。这里主要有六种缓存更新策略android

超时剔除

在 redis 中我们可以设置数据的生存时间(TTL),在超时后,redis会自动删除缓存,在下次查询该数据时,由于缓存不存在,会重新写入缓存,完成更新。

这种方法实现简单,但一致性一般,在缓存未过期之前,对数据库的数据进行增删查改都不会影响缓存,用户查到的数据始终是旧数据。

先删缓存再更新数据库

在对数据库进行更新时,先删除缓存,然后更新数据,在下次查询该数据时,由于缓存不存在,会重新将新数据写入缓存,javascript完成更新。

这种方法也无法保证数据的一致性。假设有两个线程,线程A 与 线程B , 在线程 A 更新缓存时,线程 B 发起查询,可能出现这种情况:

Redis与缓存解读

在这种情况下,一直到下次数据更新之前,缓存始终不一致,因此不推荐使用这种方法。

旁路缓存(先更新数据库,再删缓存)

在更新数据时,先更新数据库,再删除缓存,在下次查询该数据时,由于缓存不存在,会重新将新数据写入缓存,完成更新。

这种方法同样无法完全保证数据的一致性,但他是最常用的更新策略。因为它发生问题的概况较小,假设有两个线程,线程A 与 线程B , 在线程 B 更新数据库时,线程 A 发起查询,可能出现这种情况:

Redis与缓存解读

同样这种情况会出现数据不一致问题,但这种情况出现概率非常小,出现这种情况需要至少满足四个条件:

  • 读操作所读数据缓存失效
  • 有个并发的写操作
  • 写操作比读操作更快
  • 读操作早于写操作进入数据库,晚于写操作更新缓存

这样的条件是十分苛刻的,即使发生也是小概率事件,即使出现也可以通过缓存生存时间兜底。

这种方法最大的问题是删除缓存后的并发问题即缓存击穿问题,在缓存常见问题我们会介绍。

先更新数据库,再更新缓存

在更新数据时,先更新数据库,再更新缓存。

理论上这种方式比先更新数据库再删缓存有着更高的读性能,因为它事先准备好数据。但由于要更新数据库和缓存两块数据,所以它的写性能就比较低,同时他也不能完全保证数据的一致性。

假设有两个线程,线程A 与 线程B , 在线程 A B 同时更新,可能出现这种情况:

Redis与缓存解读

读写穿透

客户端只与缓存交互,缓存负责与数据库的交互。

读操作先查询缓存,如果缓存未命中,则缓存从数据库加载数据并写入缓存。写操作是直接写缓存,然后缓存同步更新数据库。这种模式下,缓存和数据库的一致性由缓存中China编程间件维护。

Redis与缓存解读

异步缓存写入模式

客户端只与缓存交互,缓存异步地将数据更新到数据库,实现最终一致性。

Redis与缓存解读

这种模式适用于写操作频繁的场景,但可能会导致数据一致性问题。

缓存常见问题

使用缓存比较常见的问题有下面三种问题:缓存击穿,缓存雪崩,缓存穿透。

缓存穿透

在我们的业务逻辑中,如果客户端访问的数据不存在于缓存我们会访问数据库,如果数据库存在数据就写入缓存,如果不存在就返回,那么如果客户端不怀好意,频繁发起对不存在数据的请求会发生什么呢?大量请求会直接打入数据库,增大后端压力,实现对服务器的攻击。

Redis与缓存解读

解决方案有很多种,最常见的有两种方法:缓存空对象,布隆过滤器

缓存空对象:当请求的数据在数据库中不存在时,我们将这个“不存在”的结果缓存起来,设置一个较短的过期时间。 这样,相同的请求在缓存失效之前会直接命中缓存,减轻数据库的压力。

Redis与缓存解读

布隆过滤器:使用布隆过滤器存储所有可能查询的键,当请求到达时,先通过布隆过滤器判断键是否存在。如果布隆过滤器认为键不存在,则直接返回,不进行数据库查询和缓存操作。

Redis与缓存解读

缓存雪崩

缓存雪崩是指在高并发系统中,大量的缓存数据在同一时间过期或被清除,导致大量请求同时涌向数据库,从而对数据库造成巨大压力,甚至可能导致数据库宕机。类似于“雪崩”。

常见的解决方法有以下几种:

设置不同的过期时间: 对于缓存中的每个数据项,设置不同的过期时间,这样可以避免大量数据同时过期。例如,可以为每个数据项的过期时间加上一个随机值。

使用互斥锁: 当缓存数据过期时,如果多个请求同时到达,使用互斥锁确保只有一个请求去查询数据库并更新缓存,其他请求等待或重试。

热点数据永不过期: 对于访问非常频繁的热点数据,可以考虑设置为永不过期,或者设置一个非常长的过期时间。

缓存击穿

在高并发的访问下,当某个热点数据缓存处于过期失效的时间点时,极有可能出现多个线程同时查询该缓存。而查询数据库更新缓存又需要消耗一定时间,在同一时间会有大量并发请求直接访问数据库而导致数据库服务器的CPU或者内存负载过高,服务能力下降甚至宕机。

那么如何解决这个问题呢?有三种解决方案。

  • 加锁:在缓存失效后,通过加锁的方式只允许一个线程查询数据和写缓存,其他线程阻塞等待。这个方法会造成部分请求等待。
  • 二级缓存:A1为原始缓存,A2为拷贝缓存。A1失效时,可以访问A2,其中A1的缓存失效时间设置为短期(比如5min),A2的缓存失效时间设置为长期(比如1天)。如果缓存value很大,此方案的缓存空间利用率低。
  • 双key:思www.chinasem.cn路和方案2类似,不同的是双key分别缓存过期时间(key-time)和缓存数据(key-data),其中(key-time)的缓存失效时间设置为短期(比如5min),(key-data)的缓存失效时间设置为长期(比如1天)。当第一个线程发现 key-time 过期不存在时,则先更新key-time,然后去查询数据库并更新key-data 的值;当其他线程来获取数据时,虽然第一个线程还没有从数据库查询完毕并更新缓存,但发现key-time存在,会直接读取缓存的旧数据返回。和二级缓存的方案对比,该方案的缓存空间利用率高。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程China编程(www.chinasem.cn)。

这篇关于Redis与缓存解读的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1153029

相关文章

详谈redis跟数据库的数据同步问题

《详谈redis跟数据库的数据同步问题》文章讨论了在Redis和数据库数据一致性问题上的解决方案,主要比较了先更新Redis缓存再更新数据库和先更新数据库再更新Redis缓存两种方案,文章指出,删除R... 目录一、Redis 数据库数据一致性的解决方案1.1、更新Redis缓存、删除Redis缓存的区别二

Redis事务与数据持久化方式

《Redis事务与数据持久化方式》该文档主要介绍了Redis事务和持久化机制,事务通过将多个命令打包执行,而持久化则通过快照(RDB)和追加式文件(AOF)两种方式将内存数据保存到磁盘,以防止数据丢失... 目录一、Redis 事务1.1 事务本质1.2 数据库事务与redis事务1.2.1 数据库事务1.

el-select下拉选择缓存的实现

《el-select下拉选择缓存的实现》本文主要介绍了在使用el-select实现下拉选择缓存时遇到的问题及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录项目场景:问题描述解决方案:项目场景:从左侧列表中选取字段填入右侧下拉多选框,用户可以对右侧

mac安装redis全过程

《mac安装redis全过程》文章内容主要介绍了如何从官网下载指定版本的Redis,以及如何在自定义目录下安装和启动Redis,还提到了如何修改Redis的密码和配置文件,以及使用RedisInsig... 目录MAC安装Redis安装启动redis 配置redis 常用命令总结mac安装redis官网下

Redis主从复制实现原理分析

《Redis主从复制实现原理分析》Redis主从复制通过Sync和CommandPropagate阶段实现数据同步,2.8版本后引入Psync指令,根据复制偏移量进行全量或部分同步,优化了数据传输效率... 目录Redis主DodMIK从复制实现原理实现原理Psync: 2.8版本后总结Redis主从复制实

SpringBoot使用注解集成Redis缓存的示例代码

《SpringBoot使用注解集成Redis缓存的示例代码》:本文主要介绍在SpringBoot中使用注解集成Redis缓存的步骤,包括添加依赖、创建相关配置类、需要缓存数据的类(Tes... 目录一、创建 Caching 配置类二、创建需要缓存数据的类三、测试方法Spring Boot 熟悉后,集成一个外

Redis分布式锁使用及说明

《Redis分布式锁使用及说明》本文总结了Redis和Zookeeper在高可用性和高一致性场景下的应用,并详细介绍了Redis的分布式锁实现方式,包括使用Lua脚本和续期机制,最后,提到了RedLo... 目录Redis分布式锁加锁方式怎么会解错锁?举个小案例吧解锁方式续期总结Redis分布式锁如果追求

Redis的Hash类型及相关命令小结

《Redis的Hash类型及相关命令小结》edisHash是一种数据结构,用于存储字段和值的映射关系,本文就来介绍一下Redis的Hash类型及相关命令小结,具有一定的参考价值,感兴趣的可以了解一下... 目录HSETHGETHEXISTSHDELHKEYSHVALSHGETALLHMGETHLENHSET

使用Spring Cache时设置缓存键的注意事项详解

《使用SpringCache时设置缓存键的注意事项详解》在现代的Web应用中,缓存是提高系统性能和响应速度的重要手段之一,Spring框架提供了强大的缓存支持,通过​​@Cacheable​​、​​... 目录引言1. 缓存键的基本概念2. 默认缓存键生成器3. 自定义缓存键3.1 使用​​@Cacheab

如何提高Redis服务器的最大打开文件数限制

《如何提高Redis服务器的最大打开文件数限制》文章讨论了如何提高Redis服务器的最大打开文件数限制,以支持高并发服务,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录如何提高Redis服务器的最大打开文件数限制问题诊断解决步骤1. 修改系统级别的限制2. 为Redis进程特别设置限制