1. 服务器中的数据库
Redis服务器将所有数据库都保存在服务器状态redis.h/redisServer结构的db数组中,db数组的每个项都是一个redis.sh/redisDb结构,每个redisDb结构代表一个数据库:
1 2 3 4 5 6 7 8 9
| struct redisServer { // ... ... // 一个数组,保存着服务区中的所有数据库 redisDb *db; // 服务器的数据库数量 int dbnum; // ... ... }
|
在初始化服务器时,程序会根据服务器状态的dbnum属性来决定应该创建多少个数据库。
2. 切换数据库
1
| redis> SELECT 2 // 切换数据库
|
在服务器内部,客户端状态redisClient结构的db属性记录了客户端当前的目标数据库,这个属性是一个指向redisDb结构的指针。
1 2 3 4 5 6
| typedef struct redisClient { // ... ... // 记录客户端当前正在使用的数据库 redisDb *db; // ... ... }
|
3. 键空间
Redis是一个键值对(key-value pair)数据库服务器,服务器中的每一个数据都是由一个redis.sh/redisDb结构表示,其中redisDb结构的dict字典保存了数据库中的所有键值对,我们将这个字段称为键空间(key space)。
1 2 3 4 5
| typedef struct redisDb { // ... ... // 数据库键空间,保存着数据库中所有的键值对 dict *dict } redisDb;
|
- 键空间的键也就是数据库的键,每个键都是一个字符串对象。
- 键空间的值也就是数据库的值,每个值是字符串对象、列表对象、哈希表对象、集合对象和有序集合对象中的任意一种Redis对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| redis> SET message "hello world" OK
redis> RPUSH alphabet "a" "b" "c" (integer)3
redis> HSET book name "Redis in Action" (integer)1
redis> HSET book author "Josiah L. Carlson" (integer)1
redis> HSET book publisher "Manning" (integer)1
|
3.1 添加新建
1
| redis> SET date "2013.12.1"
|
3.2 删除键
3.3 更新键
1
| redis> SET message "blah blah"
|
3.4 对键取值
1 2
| redis> get message "hello world"
|
3.5 其他键空间操作
1 2 3
| FLUSHDB:删除键空间中所有的键值对 RANDOMKEY:随机返回数据库中某个键 DBSIZE:返回键空间中所有键值对的数量
|
3.6 读写键空间时的维护操作
- 在读取一个键后,服务器会根据键是否存在来更新服务器的键空间命中次数和键空间不命中次数
- 在读取一个键之后,服务器会更新键的LRU时间,这个值可以用于计算键的闲置时间
- 如果服务器在读取一个键时发生该键已经过期,那么服务器会先删除这个过期键,然后才执行余下的操作
- 如果有客户端使用WATCH命令监视了某个键,那么服务器会在对被监视的键进行修改之后,会将这个键标记为脏
- 服务器每修改一个键之后,都会对脏键计数器+1,这个计数器会触发服务器的持久化和复制操作
- 如果服务器开启了通知功能,那么会在对键更新之后,服务器将按照配置发送相应的数据库通知
4. 设置键的过期时间和生存时间
EXPIRE <key> <ttl>
:将键的生存时间设置为ttl秒
PEXPIRE <key> <ttl>:
将键的生存时间设置为ttl毫秒
EXPIREAT <key> <timestamp>
:将键的过期时间设置为timestamp所指定的秒数时间戳
PEXPIREAT <key> <timestamp>
:将键的过期时间设置为timestamp所指定的毫秒数时间戳
EXPIRE -> PEXPIRE -> PEXPIREAT <- EXPIREAT
这三个命令都会转换为PEXPIREAT
5. 过期键删除策略
- 定时删除:在设置键的过期时间的同时,创建一个定时器,让定时器在键的过期时间来临时,立即执行对键的删除操作;对内存是最友好的,但是影响服务器的吞吐量和响应时间。
- 惰性删除:放任键的过期不管,但是每次从键空间中获取键时,都检查取得的键的是否已经过期,如果过期,就删除该键;如果没有过期,就返回键。
- 定期删除:每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键。至于删除多少过期键,以及要检查多少个数据库,有系统内部算法决定。
Redis服务器实际使用的是惰性删除和定期删除两种策略:通过配合使用这两种删除策略,服务器可以很好在CPU时间和避免内存浪费之间取得平衡。
6. 数据库通知
数据库通知时Redis2.8版本新增加的功能,这个功能可以让客户端通过订阅给定的频道或者模式,来获知数据库中键的变化,以及数据库中命令的执行情况。
- 键空间通知:某个键执行了什么命令。
- 键事件通知:某个命令被什么键执行了。
6.1 发送通知
6.2 发送通知的实现