2025-10-19
参考链接: https://javaguide.cn/database/redis/redis-questions-01.html#%E4%BB%80%E4%B9%88%E6%98%AF-redis
Redis是NoSQL数据库,是一种内存数据库。读写速度很快,经常用于分布式缓存方向,存储的是key-value对数据。Redis支持事务,持久化,lua脚本…
可以试一下在线编译器写一下redis命令 简单易上手 easy~
Redis为什么速度快:1.纯内存操作(纳秒级),传统的数据库需要读写磁盘(毫秒级) 2.高效的I/O模型。3.优化的内部数据结构4.简洁高效的通信协议(RESP). redis适合做缓存不适合做主数据库,因为内存成本高,且redis虽然支持数据持久化但是有数据丢失风险。 其他的分布式缓存:Tendis,KeyDB…
选择Redis的原因:1.访问速度快(基于内存) 2.高并发 3. 功能全面(可以作缓存,可以用于分布式锁,限流,消息队列,延时队列…)
常见的缓存读写策略:https://javaguide.cn/database/redis/3-commonly-used-cache-read-and-write-strategies.html
2025-10-20
Redis 应用
- 缓存
- 分布式锁 Redission
- 做限流工具 Redis+LUA脚本 RRateLimiter实现分布式限流即基于Lua脚本+令牌桶算法
- 做消息队列 Redis的Stream类型的数据结构更适合做消息队列(但一般用中间件)
- 做延时队列 内置了延时队列 基于Sorted Set实现
- 分布式session 利用String或Hash数据结构存储session数据
Redis可以实现全文搜索引擎功能 需要借助RedisSearch(一个基于Redis的搜索引擎模块):性能更优秀 较低内存占用实现快速索引。
延时任务(红包过期自动退还):实现方式:1. redis过期事件监听(不推荐) 2. redission内置的延时队列 减少了丢消息的可能,消息不存在重复消费问题
redis常见的数据类型:String、List、Set、ZSet、Hash 三种特殊数据类型:HyperLogLog(基数统计)、Bitmap (位图)、Geospatial (地理位置)
2025-10-21
Redis持久化机制:
redis支持三种持久化: 1.快照RDB,2.只追加文件AOF, 3.RDB和AOF混合持久化
1.RDB持久化 创建快照获取存储在内存种数据在某个时间点的副本 创建快照之后 可以对快照备份 可以创建副本(Redis主从结构) RDB是redis默认的持久化方式
RDB创建快照 save:同步保存操作 会阻塞Redis主线程 bgsave 用子进程执行 不会阻塞Redis主线程
2.AOF持久化 实时性更好 开启AOF持久化之后每次执行改变redis数据的命令 redis就会将该命令写入AOF缓冲区 然后再写入到AOF文件
AOF流程:所有的写命令追加到AOF缓冲区 文件写入:将AOF缓冲区的数据写入到AOF文件中 文件同步: AOF缓冲区根据对应的持久化方式向硬盘做同步操作 文件重写:AOF越来越大 需要定期对AOF文件重写 重启加载:redis重启时 可以加载AOF文件进行数据恢复
redis有三种不同的AOF持久化方式(区别在于同步AOF文件的时机不同 即刷盘时机不同): 1.appendfsync always 2.appendfsync everyseconds 3.appendfsync no
一般的关系型数据库是在执行命令前记录日志 AOF持久化机制是在执行命令之后记录日志:优点:可以避免额外开销 不会阻塞当前执行的命令 缺点:可能会造成修改丢失 可能会阻塞后续其他命令
AOF重写(当AOF文件越来越大 进行AOF重写即压缩AOF文件) Redis将AOF重写程序放在子进程执行 避免造成对redis正常处理命令请求造成影响。
Redis单线程模式和多线程模式:
对于读写命令来说,Redis 一直是单线程模型。不过,在 Redis 4.0 版本之后引入了多线程来执行一些大键值对的异步删除操作,Redis 6.0 版本之后引入了多线程来处理网络请求(提高网络 IO 读写性能)
Redis内存管理
保存的缓存数据会有一个过期时间 如果不设置过期时间 可能会出现OOM内存溢出问题 expire key 60 // 在60s后key过期 setex key 60 value // 数据在 60s 后过期(对于字符串类型) ttl key //查看数据还有多久过期 过期时间还可以用于业务场景中如登录token,验证码…
redis通过过期字典保存数据过期的时间,过期字典的key指向redis的某个key 过期字典的值指向key的过期时间 在查询key的时候 redis会首先检查一下key是否过期 即在过期字典中查找key是否存在 存在的话 进行过期删除
redis过期删除策略包括: 惰性删除(取出key时进行检查),定期删除(周期性的抽查一些key),延迟队列(将设置过期时间的key放入延迟队列 到期后删除key),定时删除(数据过期立马删除) Redis 采用的是定期删除+惰性删除结合的策略 由于定期删除是周期性的随机抽查一些数据,抽查的数据数量由expire.c决定 默认为20 定期删除的频率由hz决定 默认为10 表示每秒执行10次尝试
大量的key集中过期(缓存雪崩)造成的后果:请求延迟增加 内存占用过高,为了避免这种情况,key的过期时间尽量随机 并开启lazy free机制(异步删除过期key 不会阻塞主线程的运行)
Redis 的内存淘汰策略(6种): Redis 的内存淘汰策略只有在运行内存达到了配置的最大内存阈值时才会触发,这个阈值是通过 redis.conf 的 maxmemory 参数来定义的
2025-10-26
Redis事务
Redis 事务(并不是关系型数据库的事务),提供了一种将多个命令请求打包的功能。然后,再按顺序执行打包的所有命令,并且不会被中途打断。日常开发中一般不适用redis事务。事务的ACID特性(原子性,一致性,隔离性,持久性),redis事务不支持回滚操作,所以Redis事务不支持原子性。redis支持持久性(重启后数据还在):1.RDB快照,2.AOF只追加文件,3.混合模式
AOF持久化的实时性更好 redis的配置文件中存放了三种持久化方式(fsyn)always,everysec,no 可以通过lua脚本配合Redis事务的缺陷。
性能优化
1.可以使用批量操作减少网络传输,因为批量操作可以减少网络传输次数,减少网络开销,减少RTT(往返时延) 2.pipeline 对于不支持批量操作的命令 可以用pipeline将redis命令封装成一组 这些命令会被一次性传输给redis服务器 但是需要注意批量操作的元素个数,避免网络传输的数据量过大。 3.lua脚本 支持批量操作多条命令,可以看作是原子操作
如果 Lua 脚本运行时出错并中途结束,之后的操作不会进行,但是之前已经发生的写操作不会撤销,所以即使使用了 Lua 脚本,也不能实现类似数据库回滚的原子性
大量key集中过期(缓存雪崩)
对于过期key Redis 采用的是 定期删除+惰性删除,为了解决缓存雪崩,1.需要给key设置随机过期时间(expire)2.开启lazy-free惰性删除(异步删除key,将删除操作交给单独的子进程处理 避免阻塞主线程)
Bigkey
如果一个key对应的value占用的内存比较大 这个key可以叫bigkey(例如1MB)。bigkey消耗了更多的内存空间和带宽 还会对性能造成影响:
- 客户端超时阻塞:redis执行命令是单线程处理 如果遇到bigkey时会比较耗时
- 网络阻塞
- 工作线程阻塞:删除bigkey时会阻塞工作线程
如何找到bigkey:1.可以使用–bigkeys参数查找redis中的bigkey,2.可以用redis自带的scan命令,当redis采用的时RDB持久化的时候,3.可以用开源软件分析RDB文件找出bigkey
如何处理bigkey:1.可以将bigkey分割成小key 2.可以手动清理 3.开启惰性删除…
Hotkey
如果一个key的访问次数明显多于其他key 这个key可认为是热点key 如果hotkey处理不好 redis会直接宕机 大量请求落到数据库中 可能导致数据库崩溃
如何找到hotkey:1.当数据淘汰策略采用的是LFU最近最少访问的时候,可以用–hotkeys参数查找redis的hotkey,返回所有key被访问的次数。2.可以用monitor命令 可以实时查看redis所有操作的方式 可以监控redis实例的操作情况(不建议用)3.开源软件
如何处理hotkey:1.读写分离 主节点处理写请求 从节点处理读请求,2.可以使用redis cluster 将热点数据放在多个redis节点上 3.二级缓存(可以通过caffine/guava创建本地缓存)
慢查询命令
redis命令执行:1.发送命令 2.命令排队 3. 命令执行 4.返回结果。redis慢查询统计的是命令执行的耗时 查询的是命令执行时间较长的命令。
如何找到慢查询命令:通过查看慢查询日志,慢查询日志中记录执行时间超过指定阈值的命令。慢查询日志同样会占用一定的空间 可能会导致内存占用过高的问题。常见的命令: 查询慢日志SLOWLOG GET,清空慢日志SLOWLOG RESET,返回慢查询命令的数量 SLOWLOG LEN
Redis生产问题
1.缓存穿透(查询的数据不在缓存也不在数据库中) 解决方案:缓存空值,布隆过滤器
2.缓存击穿(热点key失效,大量并发请求访问数据库导致数据库负载过高) 解决方案:分布式锁,缓存预热,自动续期
3.缓存雪崩(大量的key同时失效,或者缓存服务器宕机 导致所有请求访问数据库)解决方案:为key设置随机过期时间 设置多级缓存 使用高可用架构(Redis集群或哨兵模式或主从架构)
缓存预热如何实现
缓存预热是防止热点数据不在缓存中 导致缓存击穿或缓存雪崩的一种解决方案 可以在系统启动或者高并发请求之前 将热点数据提前加载缓存中避免缓存失效。
缓存预热的两种实现方式:1. 使用定时任务 2.使用消息队列
缓存和数据库数据的一致性
想要保证数据库和缓存一致性,推荐采用「先更新数据库,再删除缓存」方案,并配合「消息队列」或「订阅变更日志」的方式来做。
对于1.先删除缓存,再更新数据库以及 2.读写分离 + 主从复制延迟情况下,缓存和数据不一致的问题,可以采用延迟双删策略(在更新数据库后,先删除缓存中的数据,然后延迟一段时间再删除一次缓存)。为了保证数据一致性和系统性能,只需要保证最终一致性即可 不用要求强一致性。
Redis高可用架构
实际生产中 redis如果只部署一个节点 当机器故障的时候整个系统无法提供服务(单点故障),因此在集群模式下,将redis节点部署在一台或者几台,可用提高服务的可用性。
1.主从模式:节点分为主节点和从节点 主节点进行读写操作,从节点只能进行读操作。主节点数据变化,将变化数据同步给从节点 保持数据同步(主从同步,刚刚连接的时候进行全量同步,全量同步结束之后,进行增量同步)
2.哨兵模式:主从模式下,当主节点宕机之后需要将从节点改成主节点,需要人工干预,开销大。所以在实际生产中,优先考虑哨兵模式,主节点宕机后,哨兵自动选取主节点。一般为了便于选举主节点,选用奇数个哨兵。哨兵是一个独立的进程,哨兵进程向所有的redis机器发送命令,等待redis响应 从而监控多个运行的redis实例
3.集群模式:主从模式和哨兵模式下,每台redis服务器存储相同的数据,浪费内存 。集群模式下实现redis的分布式存储,对数据进行分片,每个节点可以存储不同内容。QPS要求高的时候使用。
Redis实现延时任务
实现方式:1.redis过期事件监听 2.redisson内置的延迟队列