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

相关文章

解读GC日志中的各项指标用法

《解读GC日志中的各项指标用法》:本文主要介绍GC日志中的各项指标用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、基础 GC 日志格式(以 G1 为例)1. Minor GC 日志2. Full GC 日志二、关键指标解析1. GC 类型与触发原因2. 堆

Java设计模式---迭代器模式(Iterator)解读

《Java设计模式---迭代器模式(Iterator)解读》:本文主要介绍Java设计模式---迭代器模式(Iterator),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录1、迭代器(Iterator)1.1、结构1.2、常用方法1.3、本质1、解耦集合与遍历逻辑2、统一

Redis出现中文乱码的问题及解决

《Redis出现中文乱码的问题及解决》:本文主要介绍Redis出现中文乱码的问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 问题的产生2China编程. 问题的解决redihttp://www.chinasem.cns数据进制问题的解决中文乱码问题解决总结

MySQL之InnoDB存储页的独立表空间解读

《MySQL之InnoDB存储页的独立表空间解读》:本文主要介绍MySQL之InnoDB存储页的独立表空间,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、独立表空间【1】表空间大小【2】区【3】组【4】段【5】区的类型【6】XDES Entry区结构【

Redis的持久化之RDB和AOF机制详解

《Redis的持久化之RDB和AOF机制详解》:本文主要介绍Redis的持久化之RDB和AOF机制,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录概述RDB(Redis Database)核心原理触发方式手动触发自动触发AOF(Append-Only File)核

MySQL主从复制与读写分离的用法解读

《MySQL主从复制与读写分离的用法解读》:本文主要介绍MySQL主从复制与读写分离的用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、主从复制mysql主从复制原理实验案例二、读写分离实验案例安装并配置mycat 软件设置mycat读写分离验证mycat读

Redis分片集群、数据读写规则问题小结

《Redis分片集群、数据读写规则问题小结》本文介绍了Redis分片集群的原理,通过数据分片和哈希槽机制解决单机内存限制与写瓶颈问题,实现分布式存储和高并发处理,但存在通信开销大、维护复杂及对事务支持... 目录一、分片集群解android决的问题二、分片集群图解 分片集群特征如何解决的上述问题?(与哨兵模

SpringBoot连接Redis集群教程

《SpringBoot连接Redis集群教程》:本文主要介绍SpringBoot连接Redis集群教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 依赖2. 修改配置文件3. 创建RedisClusterConfig4. 测试总结1. 依赖 <de

SpringBoot+Redis防止接口重复提交问题

《SpringBoot+Redis防止接口重复提交问题》:本文主要介绍SpringBoot+Redis防止接口重复提交问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不... 目录前言实现思路代码示例测试总结前言在项目的使用使用过程中,经常会出现某些操作在短时间内频繁提交。例

Redis 配置文件使用建议redis.conf 从入门到实战

《Redis配置文件使用建议redis.conf从入门到实战》Redis配置方式包括配置文件、命令行参数、运行时CONFIG命令,支持动态修改参数及持久化,常用项涉及端口、绑定、内存策略等,版本8... 目录一、Redis.conf 是什么?二、命令行方式传参(适用于测试)三、运行时动态修改配置(不重启服务