1. Redis 给缓存数据设置过期时间有啥用?
内存是有限的,如果缓存中的所有数据都是一直保存的话,容易Out Of Memory。
Redis自带了给缓存数据设置过期时间的功能:
192.168.1.1>exp key 60 #数据在60s后过期
(integer)1
192.168.1.1>setex key 60 value #数据在60s后过期(setex:set+expire)
OK
192.168.1.1>ttl key #查看数据还有多久过期
(integer)56
注意:Redis中除了字符串类型有自己独有设置过期时间的命令setex外,其他方法都需要依靠expire命令来设置过期时间。
另外persist命令可以移除一个键的过期时间。
过期时间还有什么作用呢?
很多时候,业务常见中只需要某个数据在某一时间段内存在,比如我们的短信验证码只在一天内有效。
如果采用传统数据库来处理,一般都是自己判断过期,这样很麻烦而且性能差。
2.Redis是如何判断数据是否过期的呢?
Redis 中有一个叫过期字典的hash表来保存数据过期时间。
过期字典的键指向Redis数据库中的某个key(键),过期字典的值是一个long类型的整数。这个整数保存了key所指向的数据库键的过期时间(毫秒精度的UNIX时间戳)。
过期字典是存储在redisDb这个结构里:
typedef struct redosDb{
...
dict *dict;//数据库键空间,保存这数据库中所有的键值对
dict *expries;//过期字典,保存这键的过期时间
}redisDb
3.过期的数据的删除策略了解吗?
- 惰性删除:只会在取出key的时候才对数据进行过期检查,这样对CPU最友好,但是可能会造成太多过期key没有被删除
- 定期删除:每隔一段时间抽取出一批key执行删除过期key操作。并且Redis底层会通过限制删除操作执行的时长和频率来减少删除操作对CPU的影响。
定期删除对内存更加友好,惰性删除对CPU更加友好。
两者各有千秋,所以Redis采用的是定期删除+惰性/懒汉式删除。
但是,仅仅通过给key设置过期时间还是有问题的,因为还是可能存在定期删除和惰性删除漏掉很多过期key 的情况,这样就导致大量key堆积在内存里,然后就Out Of Memory了。
如何解决这个问题呢?
就是要看Redis的内存淘汰策略。
4.Redis内存淘汰机制了解么?
相关问题:MySQL里有2000w数据,Redis中只存20W的数据,如何保证Redis中的数据都是热点数据?
Redis提供6种数据淘汰策略:
- valtile-lru(least recently used):从已设置过期时间的数据集中挑选最近最少使用的数据淘汰。
- volatile-ttl:从已设置过期时间的数据集中挑选要过期的数据淘汰
- volatile-random:从已设置过期时间的数据集中任意选择数据淘汰
- allkeys-lru(least recently used):当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key
- allkeys-random:从数据集中任意选择数据淘汰
- no-eviction:禁止驱逐数据,也就是当内存不足以容纳写入新数据时,新写入操作会报错。
4.0后增加了两种:
7. volatile-lfu(least frequently used):从已设置过期时间的数据集中挑选最不经常使用的数据淘汰
8. allkeys-lfu(least frequently user):当内存不足以容纳新写入数据时,在键空间中,移除最不经常使用的key