在逛知乎时,看到这样一个问题,觉得挺不错的,将自己个人的见解分享给大家。问题是:有哪些办法可以降低 Redis 的内存使用情况?
个人也对Redis做了一个比较全面的问题汇总,希望对大家有所帮助。Redis面试题汇总
要降低内存的使用。无非就是从数据的存、数据的剔除两个方面入手。
- 数据的存,将非必要数据不存在redis中。对于必要的数据选择合适的存储数据类型。现在很多程序员一个string走天下,什么数据使劲往里塞。比如可以用bitmap、hyperloglog的场景就不要用set、zset这样的数据类型。缓存格式这种非业务类型,也需要考虑,比如把key的长度缩短。
- 数据的剔除。可以从设置合理的过期时间、内存淘汰策略方面入手考虑。讲过期数据从内存中剔除,以减少内存的使用。
数据存储
要现在合适的数据类型,我们就需要知道数据类型的底层结构。Redis底层数据结构主要有六种,这六种构成了五种常用的数据类型。其他的数据类型,例如bitmap、hyperLogLog也是基于这五大数据类型实现。具体的数据结构图如下:
- 使用短小并且具备识别度高的名称作为缓存的key。毕竟Redis的数据都是存在内存中,key对于业务数据没有什么意义,但也会占用内存。
- 对于统计一些总数并且精度不是很高的场景,可以使用bitmap、hyperloglog而不是用set、zset这样的数据类型。因为bitmap底层是一个数组,每个索引位只能是1或者0,占用的内存少。hyperloglog在底层存储的也是1和0,占用的内存也少。
数据剔除
从数据的剔除方面,需要考虑数据的过期机制、内存淘汰策略方面入手。 淘汰策略主要是真针对数据一直存在内存中,导致内存无法接纳新的数据。重点是了解lru算法、lfu算法。
针对设置了过期时间的key:
- volatile-ttl:在设置了过期时间的key中,根据过期时间的先后进行删除,越早过期的key越先被删除。
- volatile-random:在设置了过期时间的key中,随机删除一部分key,直到内存处于可用的状态。
- volatile-lru:在设置了过期时间的key中,使用LRU算法进行删除key。
- volatile-lfu:在设置了过期时间的key中,使用LFU算法进行删除key。
针对所有的key:
- allkeys-random:对所有的key进行随机删除。
- allkeys-lru:对所有的key使用lru算法进行删除。
- allkeys-lfu:对所有的key使用lfu算法进行删除。
不处理:
- noeviction:当内存不足以写入新数据时,返回错误的信息,不做任何操作(默认方式)。
由于Redis的内存淘汰策略会主动删除数据,因此会出现一种情况,没有设置过期时间的key,却被删除了。
- LRU算法(Least Recently Used,最近最少使用):淘汰很久没有被访问过的数据,以最近的一次访问时间作为参考。
- LFU算法(Least Frequently Used,最不经常使用):淘汰最近一段时间被访问次数最少的数据,以次数作为参考。
大多数情况都可以使用LRU算法;当存在大量热点缓存数据时,推荐使用LFU算法更好一些。(比如有一个热点key,在最近的5分钟内被访问的次数很少,使用LRU算法就会剔除;但是在5分钟之后,这个热点key被频繁访问。因此热点key应该以访问次数作为参考更好一些。)
过期策略是指数据在过期之后,还会占用这内容,这时候Redis是如何处理的?分别有下面三种方式:
- 定期检测,Redis在对设置了过期时间的key,在创建时都会增加一个定时器。定时器定时去处理该key。
- 定时检测,Redis会定期去检测设置了过期时间的key,当该key已经失效了,则会从内存中剔除。
- 读取检测,在客户端向Redis读数据时,Redis会检测该key是否过期,过期了就返回空值。