Redis数据库
数据库的操作及原理
服务器中的数据库切换
struct redisServer{
//一个数组,保存着服务器中所有的数据库
redisDb *db;
//服务器数据库数量
int dbnum;
...
}
在RedisServer中,每一个数据库都存在RedisServer的一个数据库数组里。我们可以通过select命令来切换数据库。根据dbnum来决定创建多少个数据库。默认情况下服务器会创建16个数据库。
struct redisClient{
...
//记录客户端正在使用的数据库,指向服务端的db
redisDb *db;
}
在客户端中的db指针用来指向服务端db数组中的一个,通过select命令切换指针。这也就是我们每次必须先打开服务端的Redis,然后再打开客户端的Redis。
数据库的键空间
每个数据库都有一个键空间(dict字典)来保存数据库中所有的键值对。键空间的键就是数据库的键,键空间的值可以是前面的任意一种对象。
键空间的操作
- 添加键
- 删除键
- 更新键
- 对键取值
- 清空整个数据库(flushdb)
- 等等
上边的这些操作底层也不难,就是从字典中找到键的位置,然后根据键来查找值,并对值进行操作。
键的一些设置
-
设置键的生存时间
-
expire:按秒设置生存时间
-
pexpire:按毫秒设置生存时间
-
-
设置过期时间
-
expireat:以时间戳的形式设定过期的时间精确到秒
-
pexireat:以时间戳的形式设定过期时间精确到毫秒(最后预算过期的最终形态,都会转换为这种形式来统一处理过期操作)
-
保存过期时间:过期时间一般都保存在一个过期字典里,里面存的都是各个键的过期时间戳。时间戳的增删改查和前面的大同小异。
-
移除过期时间:presist可以移除过期时间。原理也很简单。
-
计算并返回剩余时间:ttl可以计算剩余的生存时间并返回。
-
键不在数据库返回-2
-
没设置过期时间返回-1
-
如果存在过期时间,过期时间-当前时间并返回
-
-
判断是不是过期键:用当前时间和过期时间比较
-
过期键的删除策略
-
定时删除:对内存友好,对cpu不友好。通过设置定时器对过期键进行删除。它的缺点是,在空间充足,过期键多的情况下,会占用cpu时间,在cpu时间紧张的情况下,会加重cpu负担。
-
惰性删除:对cpu友好,对内存不友好。程序在去除键的时候才对键进行过期检测(如果过期就删除,不是过期就执行相应操作),如果有很多过期的键但是不使用它们,它们就永远不会被删除(或者手动删除数据库)。
-
定期删除:定期删除是集齐上边两种方式的优点(在规定时间内,多次遍历各个数据库,从一定数据库的一定数据进行检测并清除),每隔一段时间对过期键进行一次删除。因此选取一个合适的定期时间是很重要的。如果时间太短,对cpu不友好,时间太长就又对内存不友好了。
那在Redis到底使用的是什么策略?Redis中使用的是惰性删除和定期删除,原因嘛就很明显了,内存和cpu进行取舍,当但会偏向cpu了。
-
RDB,AOF和复制功能对过期键的处理
-
RDB
- 生成RDB时,不会保存过期的键
- 以主服务器模式载入RDB,过期间会被忽略
- 以从服务器模式载入RDB,会保存所有,但是在主从服务器同步的时候从服务器还是被清空,所以对从服务器也没影响。
-
AOF
-
AOF文件写入:如果数据库中的某个键过期但是没被删除,它会给过期的键后加一条del指令,然后获取方看到指令就不能对它进行获取了。
-
AOF重写:和RDB文件生成类似,在重写时,程序会对过期键进行检测,过期键不会被写入AOF文件。
-
-
复制:复制过程中对过期键的删除由主服务器控制
- 主服务在删除过期键后会显示的给从服务器del指令
- 在指令到达前从服务器还是照常工作
- 指令到达时,从服务器删除过期键
数据库通知
可以让客户端通过订阅给定的频道或者模式,来获知数据库中键的变化和指令的执行状况。
按ctrl+c退出,message也可以替换为删除,增添等等。
发送通知
发送通知由通知事件函数来发送,在发送通知前,程序先检测是否发通知,然后又指定发通知的事件的名称,产生通知的键和产生通知的数据库号码,将这些作为一个整体,然后当发送通知的时候,就会调用产生相关信息的函数并把相关信息发送过去。