redis当中数据库的实现

60阅读 0评论2019-08-02 stolennnxb
分类:NOSQL

redis服务器将所有数据库都保存在服务器状态redisServer结构的db数组中,db数组的每个项都是一个redisDb机构,每个redisDb结构代表一个数据库

点击(此处)折叠或打开

  1. struct redisServer{
  2.     //....
  3.     redisDb *db;
  4.     int dbnum;
  5.     //....
  6. };
  7. typedef struct redisDb {
  8.     dict *dict; /* The keyspace for this DB */
  9.     dict *expires; /* Timeout of keys with a timeout set */
  10.     dict *blocking_keys; /* Keys with clients waiting for data (BLPOP)*/
  11.     dict *ready_keys; /* Blocked keys that received a PUSH */
  12.     dict *watched_keys; /* WATCHED keys for MULTI/EXEC CAS */
  13.     int id; /* Database ID */
  14.     long long avg_ttl; /* Average TTL, just for stats */
  15. } redisDb;

其中dbnum属性的值由服务器配置选项决定。
每个redis客户端都有自己的目标数据库,每当客户端执行数据库读写命令的时候,目标数据库就会成为这些命令的操作对象。默认情况下,redis客户端的目标数据库为0号数据库,但客户端可以通过执行SELECT命令来切换目标数据库。
在服务器内部,客户端状态redisClient结构的db属性记录了客户端当前的目标数据库,这个属性是一个指向redisDb结构的指针

点击(此处)折叠或打开

  1. typedef struct redisClient{
  2.     //...
  3.     redisDb *db;
  4.     //...
  5. } redisClient;
通过修改redisClient.db指针,让它执行服务器中的不同数据库,从而实现切换目标数据库的功能,这就是SELECT命令的实现原理

redis是一个键值对数据库服务器,服务器中的每个数据库都由一个redisDb结构表示,其中dict字典当中保存了数据库中的所有键值对,我们将这个字典称为键空间:
1. 键空间的键也就是数据库的键,每个键都是一个字符串对象
2. 键空间的值也就是数据库的值,每个值可以是字符串对象、列表对象、哈希表对象、集合对象和有序集合对象中的任意一种。

redisDb结构当中的expires字典保存了数据库中所有键的过期时间:
1. 过期字典的键是一个指针,这个指针指向键空间中的某个键对象
2. 过期字典的值是个long long类型的整数,这个整数保存了键所指向的数据库键的过期时间——一个毫秒精度的UNIX时间戳(epoch)

如果一个键过期了,有三种不同的删除策略来删除对应的键与关联的时间
1. 定时删除:在设置键的过期时间的同时,创建一个定时器,让定时器在键的过期时间来临时,立即执行删除操作
2. 惰性删除:放任键过期不管,但是每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键;如果没有过期,就返回该键。redis当中的实现是:所有读写数据库的redis命令在执行之前都会调用expireIfNeeded函数对输入键进行检查,如果已经过期,则删除,如果没有过期,则不做动作
3. 定期删除:每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键。redis里面,每当redis的服务器周期性操作serverCron函数执行时,activeExpireCycle函数就会被调用,它在规定的时间内,分多次遍历服务器中的各个数据库,从数据库的expires字典中随机检查一部分键的过期时间,并删除其中的过期键,会有全局变量记录当前activeExpireCycle函数检查的进度,以便在下一次运行时继续,
在redis服务器中使用的是惰性删除和定期删除两种策略:通过配合使用这两种删除策略,服务器可以很好的在合理使用CPU时间和避免浪费内存空间之间的平衡

当服务器运行在复制模式下时,从服务器的过期键删除动作由主服务器控制,只要主服务器没有发送DEL命令,即使有客户端向从服务器请求一个过期的键,也会如愿返回。


数据库通知可以让客户端通过订阅给定的频道或者模式,来获知数据库中键的变化,以及数据库中命令的执行情况。其中,某个键执行了什么命令的通知称为键空间(key-space)通知,另一类某个命令被什么键执行了的通知称为键事件(key-event)通知
服务器配置的notify-keyspace-events选项决定了服务器所发送通知的类型,具体见官方文档。具体实现是由函数notifyKeyspaceEvent来实现的,它会根据选项设置的值,选择通知类型type,然后检测是否允许发送键空间通知,最后检测是否允许发送键事件通知


上一篇:redis补充说明之对象
下一篇:redis关于aof的一点补充