单机数据库的实现单机数据库的实现
一、数据库
(一)服务器中的数据库
所有数据库都保存在服务器状态redis.h/redisServer结构的db数组(每个项都是redisDb结构,每个redisDb结构都代表一个数
据库)中,在初始化服务器时,程序会根据服务器状态的dbnum属性来决定应该创建多少个数据库。dbnum属性的值由服务
器配置的database选项决定,默认的值是16。
(二)切换数据库 (SELECT)
每个redis客户端有自己的目标数据库,可以通过SELECT命令来切换当前数据库。
客户端没有返回当前数据库号的命令,在执行危险命令之前先显式地切换到指定的数据库,然后和执行此命令。
(三)数据库键空间
redisDb结构中的dict字典保存了数据库中所有的键值对,称之为键空间。
添加键、删除键、更新键、对键取值、清空数据库(FLUSHDB)、随机返回数据库的某个键(RANDOMKEY)、返回数据
库键数量(DBSIZE)、EXISTS、RENAME、KEYS等等,都是通过对键空间进行操作来实现的。
读写键空间时的维护操作:更新键空间的命中次数和不命中次数(INFO stats命令的keyspace_hits属性和keyspace_missess
属性中查看);更新LRU闲置时间;删除过期键;客户端使用WATCH命令监视,修改之后的键会被标记为dirty,从而让事务
程序注意到这个键已经被修改过;服务器修改一个键之后,都会对dirty键计数器加1,这个计数器会触发服务器的持久化以及
复制操作;如果服务器开启了数据库通知功能,那么在对键进行修改之后,服务器会 按照配置发送相应的数据库通知。
(四)设置键的生存时间或过期时间
EXPIRE PEXPIRE EXPIREAT PEXPIREAT TTL PTTL。
redisDb的expires字典保存数据库中所有键的过期时间,其中键保存的是键空间某个键的指针,而值则是一个long long类型的
整数,这个整数保存了键所指向的数据库键的过期时间—一个毫秒精度的UNIX时间戳。
过期键的判定:is_expired(key)。
(五)过期键的删除策略
定时删除(创建定时器,对内存友好,对cpu最不友好)、惰性删除(对CPU最友好,对内存最不友好)、定期删除(整合折
中)。
(六)redis采用的策略
惰性删除(db.c/expireIfNeeded)和定期删除(redis.c/activeExpireCycle)。
(七)AOF、RDB和复制功能对过期键的处理
1、生成RDB文件:SAVE或者BGSAVE,程序会进行过期键的检测,不会影响RDB文件的生成。
2、载入RDb文件:服务器以主服务器模式运行(过期键会被过滤),服务器以从服务器运行时(所有键都加入数据库,但是
主从服务器同步数据的时候会把从服务器数据库全部清除,因此也没有影响)。
3、AOF文件写入:程序向AOF文件追加DEL命令,显式地记录该键已被删除。
4、AOF重写:BGREWRITEAOF命令,程序检查。
5、复制:当服务器运行复制模式下时,从服务器的过期键删除动作由主服务器控制。主服务器负责删除过期键并同步,从服
务器像处理未过期的键一样来处理过期键。
(八)数据库通知(redis.conf/notify-keyspace-events)
redis命令对数据库进行修改之后,服务器会根据配置向客户端发送数据库通知。
以 keyspace 为前缀的频道被称为键空间通知(key-space notification), 而以 keyevent 为前缀的频道则被称为键事件通知
(key-event notification)。
1、发送通知:notify.c/notifyKeyspaceEvent函数实现的。
2、发送通知的实现:
二、RDB持久化