一、内存回收策略
使用redis作为缓存服务已经非常常用了,但是如果对于内存并不大的机器来说,就需要对redis占用的内存大小做限制,一般使用”maxmemory”来做限制
1 | CONFIG SET maxmemory 100mb |
但是,当你使用达到上限之后,应该如何处理这种情况呢,redis官方提供了几种策略,包括一个近似LRU回收算法。
- noeviction 这个是默认的策略,即当达到内存限制之后,如果尝试写入时只会报错
- allkeys-lru 尝试使用近似LRU算法回收最近使用较少的键
- volatile-lru 尝试使用近似LRU算法回收设置了过期时间的且最近使用较少的键
- allkeys-random 随机回收键
- volatile-random 随机回收设置了过期时间的键
- volatile-ttl 删除过期时间最近的一个键
1 | CONFIG SET maxmemory-policy volatile-lru |
回收的一般过程:
- 客户端发起了写入请求,想要添加数据
- redis检查内存使用情况,如果大于maxmemory,根据设定好的策略进行回收。
- 再执行写入请求
二、缓存策略
redis作为高速缓存的解决方案也存在一些问题
1.缓存穿透
当客户端指定查询一个缓存和数据都肯定不存在的数据的时候,如果没有做好考虑,那么会导致程序不停的去查询数据库,产生大量的数据库查询。如果并发大的时候,还有可能拖垮数据库。
解决方案:一般的做法就是,即使数据库查询的数据为空,也把空的结果放入redis中并且设置一个短的过期时间,这样下次查询的时候就直接把缓存中的数据返回,避免了缓存穿透
2.缓存雪崩
当设置的缓存数据集中在某一时刻过期的时候,此时大量的查询将直接转发到了数据库上,导致瞬间压力上升
解决方案:一般的做法是尽量避免设置同一个过期时间,可以在过期时间上加一个1-5分钟的随机值,从而保证数据不会同一时间集中过期。另外如果是经常使用的热点数据,可以设置永不过期
3.缓存击穿
如果某少数key过期之后,产生了大量的对这些key的并发请求,也会造成类似于缓存雪崩的问题。
解决方案:一般使用锁来保证,当判断缓存失效的时候,先使用SETNX方法,set一个互斥锁,操作成功之后再去访问数据库。具体如何使用redis锁的方法下一篇研究