前言
前面咱们介绍了Redis的五种数据结构,这一篇咱们换一个角度,让咱们来看看Redis服务器的数据库。单个Redis服务器默认会建立16个数据库,数据库之间的数据是相互隔离的。默认的话使用的是0库。redis
数据库
Redis服务器将全部数据库都保存在服务器状态 redis.h/redisServer结构的db数组中,db数组的每一个项都是一个redis.h/redisDb结构,每一个redisDb结构表明一个数据库。在初始化服务器时,程序会根据服务器状态的dbnum属性来决定应该建立多少个数据库,默认的话是16个。数据库
struct redisServer{ ..... //一个数组,保存着服务器中的全部数据库 redisDb *db; //服务器的数据库数量 int dbnum; .... }
服务器数据库的示例图以下:
键空间
Redis是一个键值对(key-value pair)数据库服务器,服务器中的每一个数据库都由一个redis.h/redisDb结构表示,其中,redisDb结构的dict字典保存了数据库中的全部键值对,咱们将这个字典称为键空间(key space)。数据结构以下:数组
typedef struct redisDb{ ..... //数据库键空间,保存着数据库中的全部键值对 dict *dict ..... }
须要说明的是:服务器
- 键空间和用户所见的数据库是直接对应的,也就是说当前客户端链接的是哪一个数据库,键空间就是哪一个数据库的键空间。
- 键空间的键也就是数据库的键,每一个键都是一个字符串对象。这个能够这样理解,就是说数据库中的数据都是存在键空间的。
- 键空间的值也就是数据库中的值,每一个值能够是字符串对象、列表对象、哈希表对象、集合对象和有序集合对象中的任意一种Redis对象。
下面咱们对一个空的数据库进行设值操做,咱们分别设值了一个字符串对象message,一个列表对象order,一个哈希对象book。
127.0.0.1:6379> set message "hello world" OK 127.0.0.1:6379> lpush order "111" "222" "333" (integer) 3 127.0.0.1:6379> HSET book name "Learn Redis" author zhangsan (integer) 2
其键空间的存储状况下如图所示:
数据结构
添加新键
添加一个新键值对到数据库,实际上就是将一个新键值对添加到键空间字典里面,其中键为字符串对象,而值则为任意一种类型的Redis对象。
以下图新增一个bookpage的键。
spa
HSET bookpage page 123
删除键
删除数据库中的一个键,实际上就是在键空间里面删除键所对应的键值对对象。设计
更新键
对一个数据库键进行更新,实际上就是对键空间里面键所对应的值对象进行更新,根据值对象的类型不一样,更新的具体方法有所不一样。下面以对上面的键book为例,将author的field修改为lisicode
127.0.0.1:6379> HSET book name "Learn Redis" author lisi (integer) 0 127.0.0.1:6379> hgetall book 1) "name" 2) "Learn Redis" 3) "author" 4) "lisi"
对键取值
对一个数据库键进行取值,实际上就是在键空间中取出键所对应的值对象,根据值对象的类型不一样,具体的取值方法也有所不一样。对象
读写键空间时的维护操做
- 在读取一个键以后(读操做和写操做都要对键进行读取),服务器会根据键是否存在来更新服务器的键空间命中(hit)次数或键空间不命中(miss)次数,这两个值能够在INFO status命令的keyspace_hits属性和keyspcace_misses属性中查看。
- 在读取一个键以后,服务器会更新键的LRU(最后一次使用)时间,这个值能够用于计算键的闲置时间,使用
OBJECT idletime <key>
命令能够查看键key的闲置时间。 - 若是服务器在读取一个键时发现该键已通过期,那么服务器会先删除这个过时键,而后才执行余下的其余操做。
- 若是有客户端使用WATCH命令监视了某个键,那么服务器在对监视的键进行修改以后,会将这个键标记为脏(dirty),从而让事务程序注意到这个键已经被修改过 。
总结
本文主要是参考《Redis的设计与实现第二版》写的一篇关于Redis的数据库以及数据库键空间的文章。单机的Redis服务器默认有16个数据库,对数据库的操做本质上就是对键空间的操做。blog
参考
《Redis的设计与实现第二版》