redis缓存常见问题

缓存设计中的常见问题

缓存更新策略

  1. LRU/LFU/FIFO算法剔除

    • 适用场景:缓存使用量超过了最大值
    • 一致性:清理具体哪些数据由具体算法决定,一致性较差
    • 维护成本:几乎不需要
  2. 超时剔除
    • 适用场景:业务可以容忍一段时间内,缓存层数据域存储层数据不一致
    • 一致性:一段时间窗口内存在一致性问题
    • 维护成本:不是很高
  3. 主动更新
    • 适用场景:真实数据更新后,立即更新缓存数据。例如利用消息系统或其他方式通知缓存更新
    • 一致性:高
    • 维护成本:最高。如果主动更新发生了问题,那么这条数据很可能很长时间不会更新,所以建议结合超时剔除一起使用效果会更好
  4. 最佳实践
    • 低一致性业务建议配置最大内存和淘汰策略的方式使用
    • 高一致性业务结合使用超时剔除和主动更新,这样即使主动更新出了问题,也能保证数据过期时间后删除脏数据

缓存穿透

缓存穿透指查询一个根本不存在的数据,缓存层和存储层都不会命中,导致不存在的数据请求每次都要到存储层查询。

造成缓存穿透的基本原因有:

  • 自身业务代码或数据出现问题
  • 一些恶意攻击、爬虫等造成大量空命中

1.缓存空对象

当存储层不命中后,仍然将空对象保存到缓存层中,之后再访问这个数据将会从缓存中获取。

可能会引入的问题: - 空值缓存,需要更多的内存空间:针对这类数据设置一个较短的过期时间,让其自动剔除 - 不一致问题:存储层和数据层存在不一致。可用消息系统或其他方式清掉缓存中的空对象

2.布隆滤波器过滤

将存在的 key 用布隆滤波器提前保存起来,做第一层拦截。

无底洞优化

“无底洞”现象:为了满足业务要求添加了大量新的节点,但是性能不但没有好转反而下降了。

原因:键值数据库通常采用哈希函数将 key 映射到各个节点上,造成key 的分布与业务无关,由于数据量和访问量的持续增长,造成需要添加大量节点做水平扩容,导致键值分布到更多节点上。批量操作通常需要从不同节点上获取,相当于单机批量操作只涉及一次网络操作,分布式批量操作会涉及多次网络时间。

假设批量获取n个字符串为例:

1.串行命令

逐次执行n个get命令,操作时间=n次网络时间+n次命令时间

2.串行IO

Smart客户端会保存 slot 和节点的对应关系,有了这两个数据可将属于同一个节点的 key 进行归档,得到每个节点的key子列表,之后对每个节点执行 mget 或 Pipeline 操作。操作时间=node次网络事件+n次命令时间。

3.并行IO

将上面串行IO的最后一步改为多线程执行,使用多线程网络事件变为O(1),操作时间变为:

max_slow(node网络事件) + n次命令时间

4.hash_tag实现

将多个 key 强制分配到一个节点上,操作时间=1次网络事件+n次命令时间

雪崩

缓存雪崩:缓存层由于某些原因不能提供服务,于是所有请求都会达到存储层,存储层调用量暴增,造成存储层级联宕机的情况。

解决思路:

  • 保证缓存层服务高可用性:
  • 依赖隔离组件为后端限流并降级。Hystrix依赖隔离
  • 提前演练:演练缓存层宕掉后,可能出现的问题,做一些预案设定。

热点key重建优化

如果有两个问题同时出现:

  • key 是一个热点 key ,并发量大
  • 重建缓存不能在短时间完成,可能是一个复杂计算

在缓存失效瞬间,有大量线程重建缓存,造成后端负载加大,甚至可能会让应用崩溃。

解决思路:

  1. 互斥锁:只允许一个线程重建缓存,其他线程等待重建缓存的线程执行完,重新从缓存获取数据即可。
  2. 永远不过期:

两层意思:

  • 缓存层面看:没有设置过期时间,“物理”不过期。存在一定隐患,可能会存在死锁和线程池阻塞的风险。
  • 功能层面看:为每个 value 设置一个逻辑过期时间,当发现超过逻辑过期时间,会使用单独的线程来构建缓存。会存在数据不一致的情况,且代码复杂度会增大。
时间: 2024-08-05 10:59:52

redis缓存常见问题的相关文章

redis缓存介绍以及常见问题浅析

# 没缓存的日子: 对于web来说,是用户量和访问量支持项目技术的更迭和前进.随着服务用户提升.可能会出现一下的一些状况: 页面并发量和访问量并不多,mysql足以支撑自己逻辑业务的发展.那么其实可以不加缓存.最多对静态页面进行缓存即可. 页面的并发量显著增多,数据库有些压力,并且有些数据更新频率较低反复被查询或者查询速度较慢.那么就可以考虑使用缓存技术优化.对高命中的对象存到key-value形式的redis中,那么,如果数据被命中,那么可以省经效率很低的db.从高效的redis中查找到数据.

Redis缓存你必须了解的!

不管你是从事Python.Java.Go.PHP.Ruby等等- Redis都应该是一个比较熟悉的中间件.而大部分经常写业务代码的程序员,实际工作中或许只用到了set value.get value两个操作.对Redis缺乏一个整体的认识.今天就来对Redis的常见问题做一个总结.希望能够帮助到大家 Redis是什么 Redis是一个开源的底层使用C语言编写的key-value存储数据库.可用于缓存.事件发布订阅.高速队列等场景.而且支持丰富的数据类型:string(字符串).hash(哈希).

Redis缓存服务部署

redis缓存服务部署

springboot redis 缓存对象

只要加入spring-boot-starter-data-redis , springboot 会自动识别并使用redis作为缓存容器,使用方式如下 gradle加入依赖 compile("org.springframework.boot:spring-boot-starter-data-redis:${springBootVersion}") redis configuration 中启用缓存 @Configuration @EnableCaching public class Re

asp.net性能优化之使用Redis缓存(入门)

1:使用Redis缓存的优化思路 redis的使用场景很多,仅说下本人所用的一个场景: 1.1对于大量的数据读取,为了缓解数据库的压力将一些不经常变化的而又读取频繁的数据存入redis缓存 大致思路如下:执行一个查询 1.2首先判断缓存中是否存在,如存在直接从Redis缓存中获取. 1.3如果Redis缓存中不存在,实时读取数据库数据,同时写入缓存(并设定缓存失效的时间). 1.4缺点,如果直接修改了数据库的数据而又没有更新缓存,在缓存失效的时间内将导致读取的Redis缓存是错误的数据. 2:R

使用redis缓存加索引处理数据库百万级并发

使用redis缓存加索引处理数据库百万级并发 前言:事先说明:在实际应用中这种做法设计需要各位读者自己设计,本文只提供一种思想.准备工作:安装后本地数redis服务器,使用mysql数据库,事先插入1000万条数据,可以参考我之前的文章插入数据,这里不再细说.我大概的做法是这样的,编码使用多线程访问我的数据库,在访问数据库前先访问redis缓存没有的话在去查询数据库,需要注意的是redis最大连接数最好设置为300,不然会出现很多报错. 贴一下代码吧 1 2 3 4 5 6 7 8 9 10 1

Windows环境下使用Redis缓存工具的图文详细方法

网上找了两篇关于Redis的博客,记录下! Java 使用Redis缓存工具的图文详细方法 Windows环境下使用Redis缓存工具的图文详细方法

C# mvc 前端调用 redis 缓存的信息

新手 这几天网上学习下redis ,自己总结下过程,怕之后忘记了,基本会用最简单的,有的还是不懂,先记下来,自己摸索的. 没有安装redis的先安装,教程:http://www.cnblogs.com/yyy116008/p/7508681.html 安装好了之后再配置  教程:http://www.cnblogs.com/yyy116008/p/7520635.html 安装配置好了之后: 1 传一个list集合 转化成 对象 ,值用redis缓存对象 前端代码:

Redis 缓存 + Spring 的集成示例(转载)

1. 依赖包安装 pom.xml 加入: <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.6.0.RELEASE</version> </dependency> <dependency> <groupId>redis