Redis 可以认为是一个内存数据库,我们可以向 Redis 插入多种格式的数据,这些数据同时也会占用相应的内存空间,如果只增不减,内存尽早会用完,新的数据将无法正常写入。
如何回收内存空间?
如果数据还在使用中,肯定是不能随便回收的,这样会造成数据不稳定。
DEL
通过 del 命令删除数据,硬删除,没什么好说的,乖乖释放内存就好了。
回收过期数据
Redis 可以通过 expire 命令为键设置过期时间,超过了设定的过期时间,则数据自动失效,但失效的数据并没有被删除,也就是说数据虽然失效,无法获取到,但内存空间并没有马上释放。
Redis 提供了主动和被动两种方式来回收这部分内存。
- 被动,当客户端尝试读取一个已经过期的
key时,会触发Redis删除该key。 - 主动,但有的过期
key可能永远都不会被访问,所以,仅仅靠被动方式是不够的,Redis会周期轮询判定key是否过期,过期的key会被删除。
但如果每次都轮询所有 key 的话,一个一个去判定是否过期,那么这也将是一个很耗时的操作,可能影响到 Redis 本身的响应速度,所以 Redis 采用了一种平凡的概率算法:
Redis会每秒执行10次测试,随机20个key进行过期检测,删除所有已经过期的key,如果有多于25%的key过期,重复执行,直到过期的key比例低于25%。
通过这个算法,Redis 每次清理顶多清理掉 25% 的过期数据,但可以更好地保障 Redis 的高性能,其实是一种以空间换时间的操作。
Slave 如何处理过期数据
上面讲的都是 Master 如何处理过期数据,Slave 在处理过期数据时跟 Master 不太一样。
当一个 key 过期,Master 会给 Slave 合成一个 DEL 同步命令,Slave 不会独立过期 key,而是等待 Master 的 DEL 命令。
内存已满
当向 Redis 写入数据时,检测到内存已满,无法正常写入,此时 Redis 也有可能会进行一次内存回收,这处决于 Redis 设置的 maxmemory-policy 策略。
maxmemory-policy 有以下六种策略可选
- noeviction:返回错误
- allkeys-lru:尝试回收最少使用的数据(LRU)
- volatile-lru:尝试回收最少使用的数据(LRU),但只限于设置了过期时间的数据
- allkeys-random:尝试随机回收部分数据
- volatile-random:尝试随机回收部分数据,但只限于设置了过期时间的数据
- volatile-ttl:尝试回收设置了过期时间的数据,优先回收存活时间(TTL)较短的数据。
只要不是设置的 noeviction,都会触发一次内存回收。
具体可以参考 https://www.toutiao.com/i7043506810392789541/
