1) 过期时间意外丢失
SET 除了可以设置 key-value 之外,还可以设置 key 的过期时间
127.0.0.1:6379> SET testkey val1 EX 60
OK
127.0.0.1:6379> TTL testkey
(integer) 59
此时如果想修改 key 的值,但只是单纯地使用 SET 命令,而没有加上「过期时间」的参数,那这个 key 的过期时间将会被「擦除」。
==================>SET 命令如果不设置过期时间,那么 Redis 会自动「擦除」这个 key 的过期时间。
2) DEL 竟然也会阻塞 Redis
删除一个 key 的耗时,与这个 key 的类型有关。
- key 是 String 类型,DEL 时间复杂度是 O(1)
- key 是 List/Hash/Set/ZSet 类型,DEL 时间复杂度是 O(M),M 为元素数量
也就是说,如果你要删除的是一个非 String 类型的 key,这个 key 的元素越多,那么在执行 DEL 时耗时就越久!
原因在于,删除这种 key 时,Redis 需要依次释放每个元素的内存,元素越多,这个过程就会越耗时。
而这么长的操作耗时,势必会阻塞整个 Redis 实例,影响 Redis 的性能。
在删除 List/Hash/Set/ZSet 类型的 key 时,一定要格外注意,不能无脑执行 DEL,而是应该用以下方式删除:
- 查询元素数量:执行 LLEN/HLEN/SCARD/ZCARD 命令
- 判断元素数量:如果元素数量较少,可直接执行 DEL 删除,否则分批删除
- 分批删除:执行 LRANGE/HSCAN/SSCAN/ZSCAN + LPOP/RPOP/HDEL/SREM/ZREM 删除
3) RANDOMKEY 也会阻塞 Redis
Redis 清理过期 key,是采用定时清理 + 懒惰清理 2 种方式结合来做的。
而 RANDOMKEY 在随机拿出一个 key 后,首先会先检查这个 key 是否已过期。
如果该 key 已经过期,那么 Redis 会删除它,这个过程就是懒惰清理。
清理完了还不能结束,Redis 还要找出一个「不过期」的 key,返回给客户端。
此时,Redis 则会继续随机拿出一个 key,然后再判断是它否过期,直到找出一个未过期的 key 返回给客户端。
整个流程就是这样的:
- master 随机取出一个 key,判断是否已过期
- 如果 key 已过期,删除它,继续随机取 key
- 以此循环往复,直到找到一个不过期的 key,返回
Redis 中,有大量 key 已经过期,但还未来得及被清理掉,那这个循环就会持续很久才能结束,而且,这个耗时都花费在了清理过期 key + 寻找不过期 key 上。
数据持久化
Redis 的数据持久化,分为 RDB 和 AOF 两种方式。
其中,RDB 是数据快照,而 AOF 会记录每一个写命令到日志文件中。