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
,都会触发一次内存回收。