9.1 服务器中的数据库 90
所有数据库都保存在服务器状态redisServer结构的db数组中:
struct redisServer {
// ...
redisDb *db; // 一个数组,保存着服务器中的所有数据库
int dbnum; //服务器的数据库数量
// ...
};
dbnum属性来决定应该创建多少个数据库(默认16个),可以修改。
9.2切换数据库 91
可以通过select n来选择n号数据库,比如select 0来选择0号数据库。注意在flushdb操作之前一定要select切换到目标数据库。
9.3数据库键空间 93
Redis是一个键值对(key-value pair)数据库服务器,redisDb结构的dict字典保存了数据库中的所有键值对,这个字典也称为键空间(key space):
typedef struct redisDb {
// ...
dict *dict; // 数据库键空间,保存着数据库中的所有键值对
// ...
} redisDb;
键空间的键也就是数据库的键,每个键都是一个字符串对象。
键空间的值也就是数据库的值,每个值可以是字符串对象、列表对象、哈希表对象、集合对象和有序集合对象中的任意一种Redis对象。
因为数据库的键空间是一个字典,所以所有针对数据库的操作实际上都是通过对键空间字典进行操作来实现的:
9.3.1添加新键
实际上就是将一个新键值对添加到键空间字典里面,其中键为字符串对象,而值则为任意一种类型的Redis对象。
9.3.2删除键
在键空间里面删除键所对应的键值对对象。
9.3.3更新键
对键空间里面键所对应的值对象进行更新,根据值对象的类型不同,更新的具体方法也会有所不同。
9.3.4对键取值
在键空间中取出键所对应的值对象,根据值对象的类型不同,具体的取值方法也会有所不同。
GET命令;LRANGE命令;
9.3.5其他键空间操作
FLUSHDB:清空键空间中的所有键值对。
RANDOMKEY:在键空间中随机返回一个键。
DBSIZE:返回数据库键数量
EXISTS:用于检查给定 key 是否存在
RENAME:用于修改 key 的名称
KEYS:用于查找所有符合给定模式 pattern 的 key
9.3.6读写键空间时的维护操作
当使用Redis命令对数据库进行读写时,服务器不仅会对键空间执行指定的读写操作,还会执行一些额外的维护操作。
- 在读取一个键之后,服务器会根据键是否存在来更新服务器的键空间命中(hit)次数或键空间不命中(miss)次数。
- 在读取一个键之后,服务器会更新键的LRU(最后一次使用)时间,这个值可以用于计算键的闲置时间。
- 如果服务器在读取一个键时发现该键已经过期,那么服务器会先删除这个过期键,然后才执行余下的其他操作。
- 如果有客户端使用WATCH命令监视了某个键,那么服务器在对被监视的键进行修改之后,会将这个键标记为脏(dirty),从而让事务程序注意到这个键已经被修改过。
- 服务器每次修改一个键之后,都会对脏(dirty)键计数器的值增1,这个计数器会触发服务器的持久化以及复制操作。
- 如果服务器开启了数据库通知功能,那么在对键进行修改之后,服务器将按配置发送相应的数据库通知。
9.4 设置键的生存时间或过期时间 99
9.4.1设置过期时间
Redis有四个不同的命令可以用于设置键的生存时间(键可以存在多久)或过期时间(键什么时候会被删除):
-
EXPIRE [key] [ttl]命令用于将键key的生存时间设置为ttl秒。
-
PEXPIRE [key] [ttl]命令用于将键key的生存时间设置为ttl毫秒。
-
EXPIREAT [key] [timestamp]命令用于将键key的过期时间设置为timestamp所指定的秒数时间戳。
-
PEXPIREAT [key] [timestamp]命令用于将键key的过期时间设置为timestamp所指定的毫秒数时间戳。
注:实际上EXPIRE、PEXPIRE、EXPIREAT三个命令都是使用PEXPIREAT命令来实现的
9.4.2保存过期时间
redisDb结构中的expires字典保存了数据库中所有键的过期时间(一个毫秒精度的UNIX时间戳),这个字典也称为过期字典。通过过期字典,程序可以用以下步骤检查一个给定键是否过期。
9.4.3移除过期时间
PERSIST命令就是PEXPIREAT命令的反操作: PERSIST命令在过期字典中查找给定的键,并解除键和值(过期时间)在过期字典中的关联。
9.4.4计算并返回剩余生存时间
TTL命令以秒为单位返回键的剩余生存时间,而PTTL命令则以毫秒为单位返回键的剩余生存时间。
9.4.5过期键的判定
通过过期字典,程序可以用以下步骤检查一个给定键是否过期:
- 检查给定键是否存在于过期字典:如果存在,那么取得键的过期时间。
- 检查当前UNIX时间戳是否大于键的过期时间:如果是的话,那么键已经过期;否则的话,键未过期。
9.5 过期键删除策略 107
如果一个键过期了,什么时间删除它?
三种不同的删除策略:
- 定时删除:在设置键的过期时间的同时,创建一个定时器(timer),让定时器在键的过期时间来临时,立即执行对键的删除操作。对内存友好,但定时删除占用太多CPU时间,影响服务器的响应时间和吞吐量。
- 惰性删除:多CPU友好,放任键过期不管,但是每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键;如果没有过期,就返回该键。惰性删除浪费太多内存,有内存泄漏的危险。
- 定期删除:定时删除和惰性删除的折中,每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键。至于要删除多少过期键,以及要检查多少个数据库,则由算法决定。服务器必须根据情况,合理地设置删除操作的执行时长和执行频率。
9.6 Redis的过期键删除策略 108
Redis服务器实际使用的是惰性删除和定期删除两种策略:通过配合使用这两种删除策略,服务器可以很好地在合理使用CPU时间和避免浪费内存空间之间取得平衡。
9.6.1惰性删除策略的实现
首先进入命令,判断键是否存在,不存在返回空回复,存在则再通过调用expireIfNeeded函数
判断键是否过期,过期则删除键,再返回空回复;没过期则继续执行命令的内容。
9.6.2定时删除策略的实现
每当Redis的服务器周期性操作redis.c/serverCron函数执行时,activeExpireCycle函数
就会被调用,它在规定的时间内,分多次遍历服务器中的各个数据库(前一次遍历了1-6数据库,下次则遍历7-…直至所有数据库都遍历一遍了,再循环),从数据库的expires字典中随机检查一部分键的过期时间,并删除其中的过期键。
9.7 AOF、RDB和复制功能对过期键的处理 111
还没看
9.8 数据库通知 113
这个功能可以让客户端通过订阅给定的频道或者模式,来获知数据库中键的变化,以及数据库中命令的执行情况。
关注“某个键执行了什么命令”的通知称为键空间通知(key-space notification),
键事件通知(key-event notification)关注的是“某个命令被什么键执行了”。
服务器配置的notify-keyspace-events选项决定了服务器所发送通知的类型。
9.8.1 发送通知
发送数据库通知的功能是由notify. c/notifyKeyspaceEvent函数实现的:
void noti notifyKeyspaceEvent (int type, char *event, robj *key, int dbid) ;