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,优先删除马上就要过期的数据 业务数据有明确的生命周期,需优先清理即将失效的数据,如订单超时、验证码缓存

相关推荐
梦Arrebol7 小时前
Redis 内容及相关实验
数据库·redis
只爱喝胡辣汤10 小时前
Redis Intset(整数集合)技术文档
redis
01传说11 小时前
redis开机自启脚本
数据库·redis·缓存
只爱喝胡辣汤13 小时前
Redis SDS(Simple Dynamic String)技术文档
redis
只爱喝胡辣汤13 小时前
Redis Dict(字典/哈希表)技术文档
redis
就叫_这个吧15 小时前
RabbitMQ+elasticsearch+Redis,实现新增内容并异步到es中,是否消费成功检测
redis·elasticsearch·rabbitmq
李可以量化15 小时前
Redis Client 从了解到精通(二)下:String 类型进阶操作全解
redis·git·python·量化交易·qmt
肠畔码农16 小时前
深入分布式事务内核:从 2PC/XA 到 Seata AT 模式的架构演进与权衡
分布式·架构
ai小陈16 小时前
PyTorch多GPU分布式训练实战:从单卡脚本迁移到DDP
服务器·人工智能·pytorch·分布式·深度学习·ai·gpu算力
BUG研究员_17 小时前
LangChain 向量数据库实战:Redis 与 Pinecone 的知识点总结
数据库·redis·langchain