Redis 常见缓存问题总结

 更新时间:2023年06月30日 08:46:30   作者:EzreaLwj  
这篇文章主要给大家总结了一些Redis 常见缓存问题,并介绍了解决办法,文中的图文示例介绍的非常仔细,感兴趣的同学可以参考阅读下

缓存问题

缓存雪崩

同一时间段内大量的热点 key 全部过期或者 Redis 宕机,所有的请求都打到数据库上

解决方法:

  • 给不同的 key 添加不同的 TTL ;
  • 利用 Redis 集群提高系统的可用性;
  • 当系统故障后,可以启动服务熔断机制,暂停业务对外访问,直接返回错误,不让请求访问数据库;

缓存穿透

客户端请求的数据在 Redis数据库 中都不存在,这样的缓存永远不会生效

解决方法:

  • 限制非法的请求,对请求的参数作检验
  • 缓存空对象或默认值
  • 使用布隆过滤器快速判断数据是否存在,避免通过查询数据库判断数据是否存在

布隆过滤器

我们在写入数据库时,在布隆过滤器中做一个标记。业务线程确认缓存失效后,去布隆过滤器中查询该值是否存在,而不用去数据库中进行查询;

即使发生了缓存穿透,大量请求只会查询 Redis 和布隆过滤器,而不会查询数据库,保证了数据库能正常运行,Redis 自身也是支持布隆过滤器的。

布隆过滤器由三个哈希函数一个位图数组组成:

  • 布隆过滤器先将输入的值通过三个哈希函数得到相应的哈希值;
  • 将哈希值对数组的长度取模,进而得到相应的下标;
  • 将三个下标设置为1;

判断时,布隆过滤器会读取输入的值,并通过三个哈希函数转化成三个数组下标,然后若三个下标对于值均为1,则该数据存在于布隆过滤器中,若有一个为0,则认为该数据不存在布隆过滤器中;

所以,布隆过滤器说存在数据,但实际上该数据可能不存在,布隆过滤器说不存在该数据,则该数据真的不存在;

缓存击穿

某一个热点 key 过期消失了,大量的请求打到数据库上,数据库很容易被冲垮;

解决方法:

  • 使用互斥锁来更新缓存。当某个线程成功获取锁后,进行从数据库中读取最新的数据,并把新数据存入缓存中去即可,而没有获取到锁的线程进行等待或者返回请求失败的响应即可;
  • 不给热点数据添加过期值,该 key 由我们手动删除;
  • 可以在 value 中添加逻辑过期的字段,一旦超过该时间戳就返回旧的值,再去数据库进行更新;

缓存更新问题

缓存更新策略

内存淘汰TTL 超时主动更新
说明当Redis内存达到最大值时,我们可以通过 Redis 的内存淘汰策略,淘汰部分的 key给每一个key设置过期时间,到达该过期时间后,该 key 会被自动移除通过业务的方法,更新数据库和缓存
一致性一般
维护成本一般

主动更新

更新数据库和更新缓存的顺序问题

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

出现了数据的不一致,缓存中的数据为 b,而数据库中的数据为 a

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

出现了数据的不一致,数据库中的值为 b,而缓存中的值为 a

所以,无论是「先更新数据库,再更新缓存」,还是「先更新缓存,再更新数据库」,这两个方案都存在并发问题,当两个请求并发更新同一条数据的时候,可能会出现缓存和数据库中的数据不一致的现象

更新数据库和删除缓存的顺序问题

这里我们更新数据时,不在更新缓存,而是删除缓存,当读取不到缓存时,先从数据库中读取,再写入缓存;这种叫做旁路缓存策略

写操作:

  • 更新数据库
  • 删除缓存

读操作:

  • 如果命中了缓存,直接返回数据
  • 如果没有命中缓存,则从数据库读取数据,再写入缓存
  • 先删除缓存,再更新数据库

此时也出现了数据的不一致,缓存中的数据为 a,数据库中的数据为 b

  • 先更新数据库,再删除缓存

此时也出现了数据的不一致,缓存中的数据为 a,数据库中的数据为 b

但是这种方式出现的几率会很低,因为更新缓存 a 这步操作是在Redis中进行的,更新数据库为 b 的操作是在数据库中进行的,Redis 中的写入操作比 数据库中的写入操作会快很多,所以我们一般采用 更新数据库 + 删除缓存 的手段

如果强制保存缓存为最新值,可以为缓存的 key 设置过期时间,如给 a 设置过期时间,可以作为兜底措施

  • 延迟双删,针对 先删除缓存,再更新数据库的情况

伪代码

删除缓存 	delete(x)
更新数据 	update(x)
睡眠     	sleep(N)
再次删除缓存	delete(x)

前提是:睡眠的时间要比读请求的过程要大,保证读请求写入的缓存要在再次删除缓存之前,不然再次删除缓存后还会把旧的值写入缓存

到此这篇关于Redis 常见缓存问题总结的文章就介绍到这了,更多相关Redis 缓存内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Redis 键值设计使用总结

    Redis 键值设计使用总结

    这篇文章主要介绍了Redis键值设计的使用总结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • sentinel支持的redis高可用集群配置详解

    sentinel支持的redis高可用集群配置详解

    这篇文章主要为大家介绍了sentinel支持的redis高可用集群配置详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪
    2022-04-04
  • redis如何更新升级版本

    redis如何更新升级版本

    这篇文章主要介绍了redis如何更新升级版本问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • Redis动态热点数据缓存策略设计

    Redis动态热点数据缓存策略设计

    本文主要介绍了Redis动态热点数据缓存策略设计,包括热点数据识别、动态缓存、多级缓存、预加载机制、更新策略以及监控告警等,具有一定的参考价值,感兴趣的可以了解一下
    2025-01-01
  • Redis中散列类型的常用命令小结

    Redis中散列类型的常用命令小结

    散列类型的键值其实也是一种字典解耦,其存储了字段和字段值的映射,但字段值只能是字符串,不支持其他数据类型,所以说散列类型不能嵌套其他的数据类型。下面就来详细介绍下Redis中散列类型的常用命令,有需要的可以参考学习。
    2016-09-09
  • Redis Template使用详解示例教程

    Redis Template使用详解示例教程

    RedisTemplate的底层通过RedisConnectionFactory对多种Redis驱动进行集成,上层通过RedisOperations提供丰富的API,并结合Spring基于泛型的bean注入,为开发提供了极大的便利,这篇文章主要介绍了Redis Template使用详解示例教程,需要的朋友可以参考下
    2023-11-11
  • Redis高级数据类型Hyperloglog、Bitmap的使用

    Redis高级数据类型Hyperloglog、Bitmap的使用

    很多小伙伴在面试中都会被问道 Redis的常用数据结构有哪些?可能很大一部分回答都是 string、hash、list、set、zset,但其实还有Hyperloglog和Bitmap,本文就来介绍一下
    2021-05-05
  • Redis分布式锁的使用和实现原理详解

    Redis分布式锁的使用和实现原理详解

    这篇文章主要给大家介绍了关于Redis分布式锁的使用和实现原理的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • Redis多种内存淘汰策略及配置技巧分享

    Redis多种内存淘汰策略及配置技巧分享

    本文介绍了 Redis 内存满时的淘汰机制,包括内存淘汰机制的概念,Redis 提供的 8 种淘汰策略(如 noeviction、volatile-lru 等)及其适用场景,还讲解了如何配置淘汰机制,通过合理配置可提高缓存效率和系统性能,需要的朋友可以参考下
    2025-01-01
  • Redis 缓存实现存储和读取历史搜索关键字的操作方法

    Redis 缓存实现存储和读取历史搜索关键字的操作方法

    这篇文章主要介绍了Redis 缓存实现存储和读取历史搜索关键字,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-12-12

最新评论