本章对Redis服务器的数据库实现进行详细介绍,说明服务器保存数据库的方法。
9.1 服务器中的数据库
redis将所有数据库都保存在服务器状态redis.h/redisServer
结构的db数组中。
默认会创建16个数据库
9.2 切换数据库
每个Redis客户端都有自己的目标数据库。
默认情况下Redis客户端的目标数据库为0号数据库。
9.3 数据库键空间
Redis是一个键值对数据服务器,服务器中每个数据库都有一个redis.h、redisDb
结构表示,redisDb结构中的dict字典保存了数据库中的所有键值对。
数据库键空间例子
9.3.1 添加新键
9.3.2 删除键
9.3.3 更新键
实际上就是对建空间里面的所对应的值对象进行更新。
9.3.4 对键取值
就是取出键空间中所对应的值对象。
9.3.5 其他键空间操作
flushDb
就是通过删除所有键值对来实现的。
9.3.6 读写键空间时的维护操作
其中包括:
- 读取一个键(读和写都要),服务器会根据键是否来存在更新服务器的键空间命中次数和不命中次数,可以看
keysapce_hists
和keyspace_misses
属性查看。 - 读取一个键之后,会更新LRU,用于计算键的闲置时间。
- 如果读取一个键时发现过期,就会先删除这个过期键。
- 如果客户端watch命令监视了某个键,那么服务器在堆被监视的键进行修改后,会将这个键标记为脏。
- 服务器每次修改一个键后,都会对脏键技器值增以,会触发误区七的持久化以及复制操作。
- 如果服务器开启了数据控通知功能,会触发相应数据库通知。
9.4 设置键的生存时间或过期时间
EXPIRE KEY 5
就是5秒过期时间。TTL time to live
9.4.1 设置过期时间
redis有4个不同命令可以设置。
秒、毫秒、指定timestamp\指定timestamp毫秒数。
9.4.2 保存过期时间
设置了一个expires结构来保存,并指向过期键。
9.4.3 移除过期时间
就是PERSISIT 可以移除一个键的过期时间。
9.4.4 计算并返回剩余生存时间
TTL\PTTL 秒和毫秒的结果。
9.4.5 过期键判定
1、检查键是否在过期字典中,如果在取得过期时间
2、检查当前UNIX时间戳是否大于键的过期时间,是的话就移除。
9.5 过期键删除策略
1、定时删除,在设置过期时间时创建一个timer,让定时器在键过期时间来临时,立即执行删除
2、惰性删除,过期后不管,在读取键 检查是否过期的时候再删除
3、定期删除:每隔一端时间就进行一次检查,删除里面的过期键。
9.5.1 定时删除
定是删除策略是最好的,能保证尽快删除,并释放内存。但是对cpu时间是不友好额,如果过期键过多的时候,删除就会影响相应时间。
9.5.2 惰性删除
惰性删除对cpu来说是友好的,但是这样会让其所占用内存不释放,如果有些键过期了又永远不删除可以认为是内存泄漏。
9.5.3 定期删除
定期删除的话可以减少时长和频率,以及自定义时间可以在夜晚的时候执行。
9.6 Redis的过期键删除策略
其实就是在合理使用CPU时间和避免浪费内存空间之间取得平衡。
9.6.1 惰性删除策略的实现
db.c/expireIfNeeded
函数实现。
9.6.2 定期删除策略实现
过期键的定期删除策略由redis.c/activeExpireCycle
函数实现,每当redis服务器周期性操作redis.c、serverCron
函数式,就会删除。
9.7 AOF、RDB和复制功能对过期键的处理
9.7.1 生成RDB文件
在执行SAVE命令或者BGSAVE命令创建一个新的RDB文件时,程序会对数据库键进行检查,过期的键不会保存到新创建的RDB文件中。
9.7.2 载入RDB文件
在启动redis服务器时,如果服务器开启了RDB功能,那么服务器将对RDB文件进行载入:
1、如果服务器以主服务器模式运行,那么载入的时候就会检查是否过期。
2、如果以服务器模式运行,那么所有键都会被载入。
9.7.3 AOF文件写入
当过期键被被惰性删除或者定期删除之后,程序会向AOF文件追加一条DEL命令来显式记录该键已经删除。
9.7.4 AOF重写
和生成RDB文件类似。
9.7.5 复制
当服务器运行在复制模式下时,从服务器过期键删除动作由主服务器控制。
1、主服务器会删除一个过期键之后会向slave发送一个DEL命令。
2、从服务器在执行客户端发送命令时,即使碰到过期键也不会将过期键删除
3、从服务器只有接到DEL命令之后才会删除过期键。
9.8 数据库通知
9.8.1 发送数据库通知的功能
notify.c/notifyKeySpaceEvent
函数实现。
知道发送通知类型、时间、keys、dbid产生时间的数据库号。
9.8.2 发送通知的实现
9.9 重点回顾
- redis服务器的所有数据库都保存在
redisServer.db
数组中,而数据库的数量就是由redisServer.dbnum
来控制默认16 - 客户端通过修改目标数据库指针,让它指向redisServer.db来切换不同数据库
- 数据库主要由
dict
和expires
两个字典构成,一个负责保存键值对一个负责保存过期时间。 - 数据库是由键值对构成,所以所有对数据库的操作都是建立在字典操作之上的。
- 数据库的键总是一个字符串对象、而值可以是任意对象类型比如说字符串对象、哈希对象、集合对象、列表对象和有序结合对象。
- expires字典的键指向数据库中的某个键,而值记录了数据库键的过期时间。是以unix的毫秒时间戳
- 用惰性删除和定期删除两个策略来删除过期的键。
- SAVE命令或者BGSVAE生成的RDB不会包含过期键
- AOF文件追加DEL命令来删除
- 主服务器才有删除的权利