第二章:单机数据库实现

本章将会写单独一个Redis数据的实现,比如服务器保存数据库的方法,客户端切换数据的方法,数据库保存键值对的方法,以及针对数据库的添加,删除,查看,更新操作的实现方法等。

单机数据库实现——数据库(一)

一,服务器中的数据库

在初始化服务器时,程序会根据服务器状态的dbnum属性来决定应该决定应该创建多少个数据库;默认情况下,该选项的值为16,所以Redis服务器默认会创建16个数据库。数据库结构:

struct redisServer{
	//...
	//一个数组,保存着服务器中的所有数据库
	redisDb *db;
	//...
};

二,切换数据库

当执行SELECT命令就会切换目标数据库,那么当我们再查询数据库中的数据的时候会查询目标数据库中的数据。在客户端状态redisClient结构的db属性,这个属性是一个指向redisDb结构的指针。

typedef struct redisClient{
	//...
	//记录客户端当前正在使用的数据库
	redisDb *db;
	//...
}redisClient;

三,数据库键空间

redisDb结构的dict字典保存了数据库中的所有键值对,我们将这个字典称为键空间(key space):

typedef struct redisDb{
	//...
	//数据库键空间,保存着数据库中的多有键值对
	dict *dict;
	//...
}redisDb;

添加新键

  • 添加新键值对到数据库,实际上就是将一个新键值对添加到键空间字典里面。

删除键

  • 删除数据库中的一个键,实际上就是在键空间删除键所对应的键值对象。

更新键

  • 对一个数据库键进行更新,实际上就是对键空间里面键所对应的值对象进行更新,根据键值对象的不同,更新的具体方法也会有所不同。

对键取值

  • 对一个数据库键进行取值,实际上就是在键空间中取出键所对应的值对象,根据值对象的类型不同,具体的取值方法也会有所不同。

其他键空间操作
不细说这一块了都是不常用的一些指令,比如EXISTS,RENAME,KEYS之类的。

读写键空间时的维护操作

  • 在读取一个键之后,服务器会键是否存在来更新服务器的键空间命中(hit)次数或键空间不命中次数(miss)次数,这两个值可以在INFOstats命令的keyspace_hits属性和keyspace_misses属性中查看。
  • 在读取一个键之后,服务器会更新键的LRU(最后一次使用)时间,这个值可以用于计算键的闲置时间,使用OBJECidletime命令可以查看键key的闲置时间。
  • 如果服务器在读取一个键时发现该键已经过期,那么服务器会先删除这个过期键,然后才执行余下的其他操作。
  • 如果有客户端使用WATCH命令监视了某个键,那么服务器在对被监视的键及进行修改之后,会将这个键标记为脏(dirty),从而让事务程序注意到这个键已经被修改过。
  • 服务器每次修改一个键之后,都会对脏(dirty)键计数器的值增1,这个计数器会触发服务器的持久化以及复制操作。
  • 如果服务器开启了数据库通知功能,那么在对键进行修改之后,服务器将按配置发送相应的数据库通知。