1.数据库的存储结构:
redisServer结构:
- …
- redisDb *db[]; 保存着服务器的所有数据库
- int dbum; 服务器的数据库数量,初始化默认为16
- …
redisClient结构:
- …
- redisDb *db ; 记录当前客户端的目标数据库
- …
redisDb结构:
- …
- dict *dict; 字典结构,数据库键空间
- …
键空间中存在数据库里面的所有键值对。其中键就是一个字符串,值是Redis对象的一种。对数据库键的添加删除更新,取值等操作实际上都是对键空间处理完成的。
2.设置键的生存时间或过期时间
EXPIRE/PEXPIRE命令:设置生存时间,以秒/毫秒为单位
eg:EXPIRE/PEXPIRE ttl :设置key生存时间ttl秒/毫秒
EXPIREAT/PEXPIREAT:设置过期时间为某个时间戳,以秒/毫秒为单位,
eg:EXPIREAT/PEXPIREAT timestamp : 设置key的过期时间为timestamp所制定的秒/毫秒数时间戳
PERSIST: 移除一个键的过期时间,是PEXPIREAT命令的反操作
TTL/PTTL:获取某一个键的剩余生存时间,以秒/毫秒为单位
设置生存时间和过期时间的命令最终都会被转为PERPIREAT运行,再redis中,会保存一个过期字典(字典键为某一个键对象,值为毫秒精度的时间戳)
3.过期键的删除策略
过期键的删除策略主要有三种:定时删除(过期时间到了马上删除,需要定时器),惰性删除(每次从键空间取键时再删除),定期删除(每隔一段时间删除当前所有的过期键)。Redis主要采用惰性删除和定期删除两种方式结合起来删除过期键。
- 惰性删除:由db.c/expireIfNeeded函数实现:所有读写数据库的命令在执行前都会调用这个函数对输入键进行检查,如果过期的话会将这个键从数据库中删除。
- 定期删除:由redis.c/activeExpireCycle函数实现,每当redis的服务器周期性操作redis.c/serverCron函数执行时,就会调用activeExpireCycle函数从一定量的数据库中选取一定量的随机键进行检查,同时引用一个全局变量记录已经检查过的数据库编号(current_db),以便于下次检查找到开始的数据库。
4.AOF,RDB和复制过程中对过期键的处理
4.1 RDB期间对过期键的处理
- 生成RDB文件时(SAVE,BGSAVE命令),碰到过期的键时,不会将这些过期键加入到RDB文件中
- 读取RDB文件时,若为主服务器,同样会跳过过期键;若为从服务器,无论是否过期都会将所有键加载到服务器中。不过主从服务器同步数据时从服务器的数据就会被清空,所以一般来讲,过期键对载入RDB文件的从服务器也不会有影响。
4.2 AOF期间对过期键的处理
当数据库中某个键已经过期,当还并没有被删除(定期或惰性删除未被触发),那么AOF文件不会有任何影响,当定期或惰性删除被触发时,程序会向AOF文件追加一条DEL命令,再执行AOF重写时,程序会对数据库中的键进行检查,因此不会过期键对AOF有影响。
4.3 复制
当服务器运行再复制模式下时,从服务器的过期键删除动作由主服务器控制,主要体现在:
- 主服务器删除过期键后,会发送一个DEL命令给所有的从服务器删除这个过期键
- 从服务器再执行客户端发来的读命令时,即使碰到过期键也不会将过期键删除,而是会继续像处理未过期的键一样处理这个过期键
- 从服务器只有在接到主服务器发来的DEL命令时,才会删除过期键
所以在读写分离时,可能会造成从数据库读到已经过期的脏数据的情况(没有触发惰性删除和定期删除,因此主服务器没有删除这个过期键,从服务器也就没有删除过期键),遇到这种情况,一种解决方法是用ttl命令判断一下是否过期;一种方法是升级redis到3.2,3.2以上的版本对这种情况做了处理,不会返回过期数据,详见参考资料一和二
参考资料1:http://www.cnblogs.com/bridger/archive/2012/11/07/2758734.html
参考资料2:http://www.tuicool.com/articles/INRZFr
5.数据库通知
这个功能是让客户端通过订阅给定的频道或者模式,来获知数据库中键的变化,以及数据库中命令的执行情况。配置方法主要是通过修改 redis.conf 文件, 或者直接使用 CONFIG SET 命令来开启或关闭键空间通知功能
- 当 notify-keyspace-events 选项的参数为空字符串时,功能关闭。
- 另一方面,当参数不是空字符串时,功能开启。
命令的参数可以是如下几个,但必须包含K或者E,否则不会分发通知
- K 键空间通知,所有通知以 keyspace@ 为前缀
- E 键事件通知,所有通知以 keyevent@ 为前缀
- g DEL 、 EXPIRE 、 RENAME 等类型无关的通用命令的通知
- $ 字符串命令的通知
- l 列表命令的通知
- s 集合命令的通知
- h 哈希命令的通知
- z 有序集合命令的通知
- x 过期事件:每当有过期键被删除时发送
- e 驱逐(evict)事件:每当有键因为 maxmemory 政策而被删除时发送
- A 参数 g$lshzxe 的别名