redis相关内容以及安全知识

发布于:2025-07-01 ⋅ 阅读:(25) ⋅ 点赞:(0)

1. 什么是redis

1.1 Redis简介

Redis(Remote Dictionary Server)是一个开源的、基于内存的键值存储系统,常被用作数据库、缓存和消息代理。它支持多种数据结构,如字符串、哈希、列表、集合等,并提供持久化、高可用性和分布式功能。

这是redis官网: Redis中文网https://redis.net.cn/


1.2 Redis的数据类型

Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。

String(字符串)

string是redis最基本的类型,你可以理解成与Memcached一模一样的类型,一个key对应一个value。

string类型是二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象 。

string类型是Redis最基本的数据类型,一个键最大能存储512MB。

实例

  1. redis 127.0.0.1:6379> SET name "redis.net.cn"
  2. OK
  3. redis 127.0.0.1:6379> GET name
  4. "redis.net.cn"

在以上实例中我们使用了 Redis 的 SET 和 GET 命令。键为 name,对应的值为redis.net.cn。


Hash(哈希)

Redis hash 是一个键值对集合。

Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。

实例

  1. redis 127.0.0.1:6379> HMSET user:1 username redis.net.cn password redis.net.c
    n points 200
  2. OK
  3. redis 127.0.0.1:6379> HGETALL user:1
  4. 1) "username"
  5. 2) "redis.net.cn"
  6. 3) "password"
  7. 4) "redis.net.cn"
  8. 5) "points"
  9. 6) "200"
  10. redis 127.0.0.1:6379>

以上实例中 hash 数据类型存储了包含用户脚本信息的用户对象。 实例中我们使用了 Redis HMSET, HEGTALL 命令,user:1 为键值。

每个 hash 可以存储 232 - 1 键值对(40多亿)。


List(列表)

Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素导列表的头部(左边)或者尾部(右边)。

实例

  1. redis 127.0.0.1:6379> lpush redis.net.cn redis
  2. (integer) 1
  3. redis 127.0.0.1:6379> lpush redis.net.cn mongodb
  4. (integer) 2
  5. redis 127.0.0.1:6379> lpush redis.net.cn rabitmq
  6. (integer) 3
  7. redis 127.0.0.1:6379> lrange redis.net.cn 0 10
  8. 1) "rabitmq"
  9. 2) "mongodb"
  10. 3) "redis"
  11. redis 127.0.0.1:6379>

列表最多可存储 232 - 1 元素 (4294967295, 每个列表可存储40多亿)。


Set(集合)

Redis的Set是string类型的无序集合。

集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。

sadd 命令

添加一个string元素到,key对应的set集合中,成功返回1,如果元素以及在集合中返回0,key对应的set不存在返回错误。

  1. sadd key member

实例

  1. redis 127.0.0.1:6379> sadd redis.net.cn redis
  2. (integer) 1
  3. redis 127.0.0.1:6379> sadd redis.net.cn mongodb
  4. (integer) 1
  5. redis 127.0.0.1:6379> sadd redis.net.cn rabitmq
  6. (integer) 1
  7. redis 127.0.0.1:6379> sadd redis.net.cn rabitmq
  8. (integer) 0
  9. redis 127.0.0.1:6379> smembers redis.net.cn
  10. 1) "rabitmq"
  11. 2) "mongodb"
  12. 3) "redis"

注意:以上实例中 rabitmq 添加了两次,但根据集合内元素的唯一性,第二次插入的元素将被忽略。

集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。


zset(sorted set:有序集合)

Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。

不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。

zset的成员是唯一的,但分数(score)却可以重复。

zadd 命令

添加元素到集合,元素在集合中存在则更新对应score

  1. zadd key score member

实例

  1. redis 127.0.0.1:6379> zadd redis.net.cn 0 redis
  2. (integer) 1
  3. redis 127.0.0.1:6379> zadd redis.net.cn 0 mongodb
  4. (integer) 1
  5. redis 127.0.0.1:6379> zadd redis.net.cn 0 rabitmq
  6. (integer) 1
  7. redis 127.0.0.1:6379> zadd redis.net.cn 0 rabitmq
  8. (integer) 0
  9. redis 127.0.0.1:6379> ZRANGEBYSCORE redis.net.cn 0 1000
  10. 1) "redis"
  11. 2) "mongodb"
  12. 3) "rabitmq"

2.redis缓存穿透

缓存穿透:

查询一个不存在的数据,mysal查询不到数据也不会直接写入缓存,就会导致每次请求都查数据库

 这种情况可能由恶意攻击或频繁查询无效数据引发,给数据库带来巨大压力。


缓存穿透的典型场景

  • 恶意攻击:攻击者故意请求不存在的数据(如无效ID或随机键)。
  • 业务错误:用户输入非法参数(如负数ID),而系统未校验。

缓存穿透的解决方案

布隆过滤器(Bloom Filter)
在缓存层前加布隆过滤器,快速判断数据是否存在。若布隆过滤器返回“不存在”,则直接拒绝请求;若返回“可能存在”,才查询缓存或数据库。布隆过滤器需定期同步数据库中的合法键。

优点:内存占用少,没有多余的key

缺点:实现复杂,存在误判率(误差)

 

缓存空对象
即使数据库查询结果为空,仍将空结果(如NULL或特殊标记)写入缓存,并设置较短过期时间。后续请求会命中空对象,避免重复穿透。需注意内存占用和数据一致性问题。

优点:简单易操作

缺点:消耗内存,可能发生不一致问题


3.redis缓存击穿

缓存击穿:

给某一个key设置了过期时间,当key过期的时候,恰好这时间点对这个key有大量的并发请求过来,这些并发的请求可能会瞬间把DB压垮

 


缓存击穿的核心问题

  1. 热点数据集中访问:高并发请求同时查询同一个不存在/已失效的缓存键。
  2. 瞬时数据库压力:大量请求直接落到数据库,可能引发连接池耗尽或性能瓶颈。
  3. 恶性循环:数据库响应变慢进一步加剧请求阻塞,形成连锁反应。

缓存击穿的解决方案:

互斥锁(Mutex Lock)

当缓存失效时,通过分布式锁(如Redis的SETNX)确保只有一个请求能访问数据库并重建缓存,其他请求等待或轮询缓存。

优点:保证数据强一致性

缺点:可能产生等待延迟,性能差

逻辑过期时间

缓存数据不设置物理TTL,而是嵌入逻辑过期时间字段。业务代码判断是否过期,若过期则触发异步重建,未过期直接返回旧数据。

优点:高可用性,性能比较好

缺点:实现复杂度较高,不能保证数据绝对一致


4.redis缓存雪崩

缓存雪崩:

缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,带来巨大压力。

缓存雪崩的常见原因

  1. 缓存集中过期:大量缓存键设置相同的过期时间,导致同时失效。
  2. 缓存服务宕机:Redis等缓存服务集群故障,无法提供服务。
  3. 热点数据并发:突发流量导致缓存未命中,请求直接压垮数据库。

缓存雪崩解决方案:

分散过期时间

为缓存键设置随机的过期时间(TTL),避免同时失效。例如在原定过期时间基础上增加随机值

高可用设计

对Redis等缓存服务采用集群模式(如哨兵或Cluster),避免单点故障。同时设置从库快速切换机制。

熔断与降级机制

在数据库压力过大时,通过熔断器(如Hystrix)暂时拒绝请求或返回降级内容(如默认值、缓存旧数据),保护数据库。

多级缓存架构

构建本地缓存(如Caffeine)+分布式缓存(如Redis)的多层体系。当分布式缓存失效时,本地缓存仍能缓解部分压力。


5.redis双写一致性

双写一致性:

当修改了数据库的数据也要同时更新缓存的数据,缓存和数据库的数据要保持一致

读操作:缓存命中,直接返回;缓存未命中查询数据库,写入缓存,设定超时时间。

写操作:采用 延时双删策略

延时双删策略

写入数据库前先删除Redis缓存 写入数据库后再次删除Redis缓存(延迟一定时间) 设置延迟是为了确保读请求完成并可能将旧数据写入缓存


双写强一致性

采用分布式锁

但是由于缓存都是“读多写少”我们可以采用以下两种情况:

共享锁:读锁readLock,加锁之后,其他线程可以共享读操作

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

注意事项

强一致性方案通常影响性能,


6.redis持久化

Redis持久化的两种主要方式

Redis提供了两种主要的持久化机制:RDB(Redis Database)和AOF(Append Only File)。这两种方式各有优缺点,适用于不同的场景。

RDB持久化

RDB全称Redis Database Backup file(Redis数据备份文件),也被叫做Redis数据快照。所有数据都记录到磁盘中。当Redis实例故障重启后,从磁盘读取快照文件,恢复数据简单来说就是把内存中的。

RDB的配置通常在redis.conf文件中进行: 

save 900 1      # 900秒内至少有1个键被改动
save 300 10     # 300秒内至少有10个键被改动
save 60 10000   # 60秒内至少有10000个键被改动
 
RDB的执行原理

basave开始时会fork主进程得到子进程,子进程共享主进程的内存数据。完成fork后读取内存数据并写入 RDB 文件。

fork采用的是copy-on-write技术

  • 当主进程执行读操作时,访问共享内存
  • 当主进程执行写操作时,则会拷贝一份数据,执行写操作,

RDB的优点包括:

  • 紧凑的单一文件便于备份和灾难恢复
  • 最大化Redis性能,因为父进程不需要参与磁盘I/O
  • 重启时恢复大数据集速度比AOF快

RDB的缺点包括:

  • 可能丢失最后一次快照后的数据
  • 数据集较大时,fork子进程可能耗时较长

AOF持久化

AOF持久化记录服务器接收到的每个写操作命令,并在服务器启动时重新执行这些命令来恢复数据。可以吧AOF看做是 命令日志文件

AOF的配置选项: 

appendonly yes          # 启用AOF
appendfsync everysec    # 每秒同步一次
# appendfsync always    # 每次写操作都同步
# appendfsync no        # 由操作系统决定同步时机
 

AOF的优点包括:

  • 更好的持久性保障,可配置为每秒或每次操作同步
  • AOF日志是仅追加的,没有寻址问题
  • 当AOF文件过大时,Redis会自动重写AOF文件

AOF的缺点包括:

  • AOF文件通常比RDB文件大
  • 根据使用的fsync策略,AOF可能比RDB慢
  • 特定命令下可能遇到AOF重写bug

混合持久化模式

Redis 4.0开始支持RDB-AOF混合持久化模式。这种模式下,AOF重写时会先生成RDB格式的数据,再将增量命令以AOF格式追加。

启用混合持久化的配置: 

aof-use-rdb-preamble yes
 

这种模式结合了RDB的快速恢复和AOF的低数据丢失风险,是目前推荐的持久化方案。


RDB和AOF的对比


7.redis数据过期策略

Redis数据过期策略

Redis通过两种主要机制处理键的过期:被动过期主动过期

被动过期(惰性删除)

当客户端尝试访问一个键时,Redis会检查该键是否设置了过期时间且已过期。如果过期,Redis会立即删除该键并返回空值。

这种方式节省CPU资源,但可能导致大量过期键占用内存直到被访问。

优点:对CPU友好,只会在使用该key时才会进行过期检查,对于很多用不到的key不用浪费时间进行过期检查
缺点:对内存不友好,如果一个key已经过期,但是一直没有使用,那么该key就会一直存在内存中,内存永远不会释放

主动过期(定期删除)

Redis每隔一段时间(默认每秒10次)随机抽取一定数量的键(默认20个)检查是否过期。如果发现过期键,立即删除。

如果抽样中过期键比例超过25%,会继续抽样直到比例低于25%。

定期清理有两种模式:

  • SLOW模式是定时任务,执行频率默认为10hz,每次不超过25ms,以通过修改配置文件redis.conf的hz 选项来调整这个次数
  • FAST模式执行频率不固定,但两次间隔不低于2ms,每次耗时不超过1ms

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


8.redis数据淘汰策略

数据淘汰策略

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

 Redis支持8种不同的策略来删除key

noeviction
默认策略,不淘汰任何数据。当内存不足时,新写入操作会返回错误(如OOM)。适用于不允许数据丢失的场景。

volatile-lru
从已设置过期时间(TTL)的键中,淘汰最近最少使用(LRU)的键。适合对冷数据敏感的场景。

allkeys-lru
从所有键中淘汰最近最少使用的键,无论是否设置过期时间。适用于缓存场景,优先保留热点数据。

volatile-lfu
从已设置过期时间的键中,淘汰使用频率最低(LFU)的键。适合访问频率差异明显的场景。

allkeys-lfu
从所有键中淘汰使用频率最低的键。适用于需要长期保留高频访问数据的场景。

volatile-random
随机淘汰已设置过期时间的键。适合对淘汰顺序无特殊要求的场景。

allkeys-random
随机淘汰任意键。适用于数据重要性均匀分布的情况。

volatile-ttl
优先淘汰剩余生存时间(TTL)最短的键。适合需要快速清理过期数据的场景。

配置方法

redis.conf文件中设置以下参数:

maxmemory <bytes>      # 指定最大内存限制(如100mb)
maxmemory-policy <策略名>  # 如allkeys-lru
 

选择建议

  • 优先使用 alkeys-lru 策略。充分利用 LRU 算法的优势,把最近最常访问的数据留在缓存中。如果业务有明显的冷热数据区分,建议使用。

  • 如果业务中数据访问频率差别不大,没有明显冷热数据区分,建议使用 alkeys-random,随机选择淘汰。

  • 如果业务中有置顶的需求,可以使用 volatile-lru 策略,同时置顶数据不设置过期时间,这些数据就一直不被删除会淘汰其他设置过期时间的数据。

  • 如果业务中有短时高频访问的数据,可以使用 alkeys-lfu 或 volatile-lfu 策略

 注意:LRU/LFU算法均为近似实现,Redis使用采样法平衡性能与精度。

9.redis分布式锁

10.面试问题

不定时更新!!!


网站公告

今日签到

点亮在社区的每一天
去签到