以下内容来自:《Redis 设计与实现》
数据库键空间
Redis 是一个键值对(key-value pair)数据库服务器,服务器中的每个数据库都由I个 redis/redisDb 结构表示,其中,redisDb 结构的 dict 字典保存了数据库中的所有键值对,这个字典称为键空间(key space)。
1 | typedef struct redisDb { |
键空间和用户所见的数据库是直接对应的:
- 键空间的键也就是数据库的键,每个键都是一个字符串对象。
- 键空间的值也就是数据库的值,每个值可以是字符串对象、列表对象、哈希表对象、集合对象和有序集合对象中的任意一种 Redis 对象。
设置建的生存时间和过期时间
过期字典
redisDb 结构的 expires 字典保存了数据库中所有键的过期时间,我们称这个字典为过期字典:
- 过期字典的键是一个指针,这个指针指向键空间中的某个键对象(即某个数据库键)。
- 过期字典的值是一个 long long 类型的整数,这个整数保存了键所指向的数据库键的过期时间——一个毫秒精度的 UNIX 时间戳。
EXPIRE/PEXPIRE
给数据库中某个键设置生存时间(Time To Live,TTL),即键可以存在多久。
Redis PEXPIRE 命令和 EXPIRE 命令的作用类似,都是为数据库中某个键设置生存时间(在经过指定的秒数或者毫秒数之后,服务器就会自动删除生存时间为 0 的键),但是 PEXPIRE 命令 以毫秒为单位, EXPIRE 命令以秒为单位。
- EXPIRE
命令用于将键 key 的生存时间设置为 ttl 秒。 - PEXPIRE
命令用于将键 key 的生存时间设置为 ttl 毫秒。
EXPIREAT/PEXPIREAT
给数据库中某个键设置过期时间(Expire Time),即键什么时候会被删除。
- EXPIREAT
命令用于将键 key 的过期时间设置为 timestamp 所指定的秒数时间戳。 - PEXPIREAT
命令用于将键 key 的过期时间设置为 timestamp 所指定的毫秒数时间戳。
过期键的判定
- 检查给定键是否存在于过期字典中:如果存在,那么取得键的过期时间。
- 检查当前 UNIX时间戳是否大于键的过期时间:如果是,那么键已经过期,否则,键未过期。
TTL/PTTL
查询数据库中某个键的剩余生存时间。TTL 和 PTTL 两个命令都是通过计算键的过期时间和当前时间之间的差来实现的。
TTL 命令以秒为单位返回键的剩余生存时间,而 PTTL 命令则以毫秒为单位返回剩余键的剩余生存时间。
PERSIST
移除过期时间。PERSIST 命令是 PEXPIREAT 命令的反操作:PERSIST 命令在过期字典中查找给定的键,并解除键和值(过期时间)在过期字典中的关联。
过期键的删除策略
删除过期键的三种可能的策略:
- 定时删除:在设置键的过期时间的同时,创建一个定时器(Timer),让定时器在键的过期时间来临时,立即执行对键的删除操作。该策略对 CPU 不友好,对内存友好。
- 惰性删除:放任键过期不管,但是每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键;如果没有过期,就返回该键。该策略对 CPU 友好,对内存不友好。
- 定期删除:每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键。至于要删除多少过期键,以及要检查多少个数据库,则有算法决定。该策略是上面两种策略的折中。
在上面的三种策略中,第一种和第三种为主动删除策略,而第二种则为被动删除策略。
Redis 服务器实际使用的是惰性删除和定期删除两种策略。
内存淘汰策略
定期删除和惰性删除都不能及时删除掉已经过期的键,所以当某时刻大量键堆积在内存里,导致 Redis 内存快耗尽了,还需要用到 Redis 的内存淘汰策略。
eviction policy:
1 | volatile-lru:在所有设置了过期时间的键中,淘汰掉最近最少使用(LRU,least recently used) 的一个键。 |
如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理