redis缓存

目录

redis双写一致性

方法一:延迟双删

方法二:分布式锁

redis持久化

RDB

​编辑

AOF

redis数据过期策略

惰性删除

定期删除

redis数据淘汰策略

​编辑


redis双写一致性

如果将redis作为缓存,当修改了数据库中的数据同时也要更新缓存的数据,缓存和数据库中的数据应该如何保持一致呢?这里就出现了redis双写一致性的问题

方法一:延迟双删

那么这时候又出现了一个问题,究竟是先删除缓存中的数据呢,还是先修改数据库呢?其实不管是先删除缓存还是先删除数据库,其实都存在一些问题,接下来一个一个来分析
先删除缓存,再操作数据库的情况:

通过上图中就可以发现,出现线程不安全问题,就会导致最终缓存与数据库中的值不一致问题,那么接下来我们来看看先操作数据库再删除缓存的情况:

此时通过上图中就可以发现,出现线程不安全问题,也会导致最终缓存与数据库中的值不一致问题

那么我们现在来讨论一下为什么要删除两次缓存,这是因为在分布式下,一般数据库都存在主从模式,那么主数据库需要将数据同步到从数据库,这时候redis可能会往从数据库更新缓存,这时候就会出现脏数据问题,所以需要延迟一会等待从数据库也更新完毕,但是这样子也只是控制一一大部分脏数据的风险,并不能完全解决,没有办法做到绝对的强一致性,那么如果需要保持一致应该怎么做呢?

方法二:分布式锁

想必大家心里都知道,对于线程安全问题我们可以通过加锁来解决这个问题,那么解决这个问题就可以保证数据强一致啦。

但是加锁往往带来的是性能问题,创建锁和销毁锁的开销加上阻塞的时间,这都会产生性能上的问题,那么这个问题应该如何进行优化呢?

对于大部分情况下,对于redis的操作都是读多写少,那么这时候我们就可以使用共享锁+排他锁来进行性能优化

共享锁:读锁readLock,加锁之后,其他线程可以共享读操作,但是不能进行写操作

排他锁:独占锁writeLock,加锁之后,阻塞其他线程的读写操作

通过共享锁+排他锁的引入,那么在修改数据的时候不允许读写操作,那么就不会出现数据不一致问题,但是当读数据的时候,其他线程也可以进行读操作,不会影响多个线程读操作优化了性能问题,但是性能还是不太高的

所以redis双写一致性问题,需要进行业务进行具体分析,如果需要数据强一致性,那么就采用redisson中的读写锁来保证数据同步,如果对实时性要求没那么高只需要保证最终一致性的话,那么采用异步的方案同步数据是比较好的

redis持久化

redis作为一种数据库,我们需要保证数据的持久化,那么下面我们就来了解一下redis中是如何保证数据的持久化的

RDB

RDB全称Redis Database Backup file(Redis 数据备份文件),也叫做Redis数据快照,就是将内存中的所有数据都记录到磁盘中,当Redis出现故障重启后,从磁盘读取快照文件进行数据恢复

RDB可以进行主动备份:

save命令:由Redis主进程来执行RDB,会阻塞所有命令

basave命令:开启子进程执行RDB,避免主进程收到影响

Redis内部有触发RDB的机制:

#900秒内,如果至少有1个key被修改,则执行bgsave

save 900 1

#300秒内,如果至少有10个key被修改,则执行bgsave

save 300 10

#60秒内,如果至少有10000个key被修改,则执行bgsave

save 60 10000

这里的配置也可以在redis.conf文件中自定义配置

RDB执行原理:

  1. Redis 主进程调用 fork() 生成子进程

  2. 子进程和主进程共享同一块内存物理页面,不拷贝数据,瞬间完成创建

  3. 子进程:遍历内存数据,全程阻塞写入 .rdb 文件,生成快照

  4. 主进程:继续正常处理客户端读写请求

  5. 若主进程修改某数据:触发写时复制,单独拷贝一份新页面给主进程,子进程依旧保留快照旧数据,互不干扰

复制代码
客户端/配置触发 bgsave
        ↓
Redis 主进程
        │
        ├─ 调用 fork()  创建子进程
        │       ↓
        │    子进程(专门做RDB)
        │       │
        │       │  共享主进程内存页(COW写时复制)
        │       │
        │       ├─ 遍历所有DB、所有Key
        │       │
        │       ├─ 按Redis二进制格式序列化
        │       │
        │       ├─ 写入临时 .rdb 临时文件
        │       │
        │       └─ 写完原子替换为 dump.rdb → 子进程退出
        │
        ↓
主进程继续正常处理 增删改查 请求
        │
        └─ 若有客户端修改数据 → 触发COW,复制新内存页
             子进程依然用旧快照数据,互不干扰

AOF

AOF全称为Append Only File(追加文件) redis处理的每一个写命令都会记录在AOF文件中,可以看作是一个记录命令日志的文件

AOF默认是关闭的,需要在redis.conf配置文件中开启:appendonly yes(默认是no)

AOF的命令记录频率也可以通过redis.conf文件来配置:

appendfsync always //表示每执行一次写命令,立即记录到AOF文件中

appendfsync everysec //写命令执行完后先放入AOF缓冲区,每隔1秒中将缓冲区中的数据写入到AOF文件中,是默认方案

appendfsync no //写命令执行完后先放入AOF缓冲区,由操作系统决堤的那个什么时候将缓冲区的内容写入磁盘

AOF重写:AOF重写是指AOF会记录对同一个key的多次写操作,但是只有最后一次写操作才有意思,那么通过执行bgrewriteaof命令,就可以让AOF文件执行重写操作,用最少的命令达到相同的效果,使得AOF文件不那么大

在redis中也有触发自动重写的阈值,可以在redis.conf中配置:

auto-aof-rewrite-percentage 100 // 表示AOF比上一次文件,增长超过多少百分比就触发重写

auto-aof-rewrite-min-size64mb //表示AOF文件体积最小多大以上触发重写

RDB和AOF对比:

RDB和AOF都有自己的优缺点,如果对数据安全性要求比较高,那么实际开发中往往会结合两者使用,日常RDB 存全量快照做备份,AOF 记增量命令保数据;重启优先读 AOF,redis4.0 混合持久化(AOF 文件开头是 RDB 全量快照 + 后面是增量 AOF 命令日志)把 RDB 嵌进 AOF,兼顾速度和安全。

redis数据过期策略

在redis中key过期后需要将数据从内存总删除掉,那么就可以按照不同的规则进行删除,这种删除策略就被称之为数据的过期策略

惰性删除

惰性删除:当设置了key的过期时间后,就需要去管了,当需要该key时,再进行检查是否过期,如果过期了就删除,没过期就返回

优点:对CPU友好,只会在使用key时才会进行过期检查,对于很多用不到的key不用浪费时间进行过期检查

缺点:如果一个key过期了,但是一直没有使用,那这个key就会一直存在在内存中,内存永远得不到释放

定期删除

定期删除:每隔一段时间,就会对一些key进行检查,删除里面过期的key(随机key进行检查,并删除过期key)

定期清理的两种模式:

SLOW:执行频率默认为10hz,每次不超过25ms

FAST:执行频率不固定,但是两次间隔不低于2ms,每次耗时不超过1ms

优点:可以通过限制删除操作和执行的时长和频率来减少删除操作对CPU的影响,也能有效释放过期key占用的内存

缺点:难以确定删除操作执行时长和频率

在redis中的过期删除策略中,是惰性删除和定期删除两种策略进行配合使用的

redis数据淘汰策略

当redis内存不够的时候,这时候再向redis中添加新数据,那么redis就会按照某一种规则将内存中的数据删除掉,这种数据删除规则被称之为内存淘汰策略

策略分类 策略名称 淘汰数据范围 核心淘汰规则 典型适用场景
不淘汰类 noeviction 无(不删除任何数据) Redis 默认策略,内存达上限后,所有写操作直接返回错误,仅支持读操作 核心数据不允许丢失、可接受写失败的业务场景
全量 Key 淘汰类(所有 Key 均参与淘汰) allkeys-lru 整个 Redis 实例的所有 Key(无论是否设置过期时间) 淘汰 最近最少使用(LRU)的 Key,优先删除长时间未访问的数据 通用业务场景,大部分 Redis 集群的首选策略,兼顾性能与内存利用率
全量 Key 淘汰类 allkeys-lfu 整个 Redis 实例的所有 Key(无论是否设置过期时间) 淘汰 访问频率最低(LFU)的 Key,优先删除累计访问次数最少的数据 热点流量、高频访问业务,如电商秒杀、热门内容缓存,精准保留高价值热数据
全量 Key 淘汰类 allkeys-random 整个 Redis 实例的所有 Key(无论是否设置过期时间) 完全随机选择 Key 进行删除,无任何访问规则偏好 对数据访问无明显冷热区分、业务逻辑简单的场景
过期 Key 专属淘汰类(仅参与设置了过期时间的 Key) volatile-lru 仅设置了过期时间的 Key 在过期 Key 范围内,淘汰 最近最少使用(LRU) 的 Key 业务数据有明确过期周期,同时需优先保留近期访问的有效数据
过期 Key 专属淘汰类 volatile-lfu 仅设置了过期时间的 Key 在过期 Key 范围内,淘汰 访问频率最低(LFU) 的 Key 有过期规则的高频访问业务,如限时活动、会员权益缓存,精准保留高访问量的有效数据
过期 Key 专属淘汰类 volatile-random 仅设置了过期时间的 Key 在过期 Key 范围内,完全随机选择 Key 进行删除 对过期数据无访问偏好、业务逻辑简单的场景
过期 Key 专属淘汰类 volatile-ttl 仅设置了过期时间的 Key 在过期 Key 范围内,淘汰剩余存活时间(TTL)最短的 Key,优先删除马上就要过期的数据 业务数据有明确的生命周期,需优先清理即将失效的数据,如订单超时、验证码缓存

相关推荐
环流_1 小时前
Redis中set类型以及应用场景
数据库·redis·缓存
liux35281 小时前
Kafka 4.1.1 生产环境调优与最佳实践指南
数据库·分布式·kafka
明月_清风1 小时前
Redis 数据类型全景解析:从基础到高阶,一文掌握九大核心结构与应用场景
redis·后端
189228048611 小时前
NV236美光MT29F32T08GWLBHD6-24TES:B
大数据·服务器·人工智能·科技·缓存
難釋懷1 小时前
Redis网络模型-异步IO
网络·数据库·redis
StackNoOverflow2 小时前
RabbitMQ 从入门到实战:详解安装、五种消息模型及持久化
分布式·rabbitmq
代码讲故事2 小时前
Redis生产环境批量的key需要删除,如何优雅实现且不影响线上环境?有密码认证的如何实现批量删除?有哪些实现方法?
运维·redis·缓存·高并发·删除·批量·生产环境
Devin~Y2 小时前
大厂Java面试实录:Spring Boot + JVM + Redis/Kafka + 微服务治理 + Spring AI/RAG 一条龙
java·jvm·spring boot·redis·spring cloud·kafka·openfeign
闵孚龙2 小时前
Claude Code 缓存架构与断点设计全解析:Prompt Cache、上下文工程、Token 成本优化、AI Agent 长会话性能治理
人工智能·缓存·架构·prompt·claude