Redis设计与实现(八)数据库

24章今天一定要弄到10章!

Redis服务器将所有数据库都保存在服务器状态redis.h/redisServer结构的db数组中,db数组中的每个项都是一个redis.h/redisDb结构,每个redisDb都表示着一个数据库:

在redisServer使用一个数组来保存数据库。

 

 在初始化的时候会通过redisServer中的dbnum来决定创建多少个数据库。dbnum属性的值由服务器配置的database选项决定,默认情况下创建16个数据库。如下图所示

 

 客户端可以通过SELECT命令来对数据库进切换。SELECT的逻辑就是改变指针的引用

在服务器内部是通过redisClient结构的db属性记录客户端当前目标的数据库。redisClient.db指针指向redisServier.db数组中的某一个元素。

 

 Redis是一个键值对的数据库,思想是极致的节省内存,每个数据库都是redisDb数组中的一个,其中redisDb中的dict字典保存了数据库中的所有键值对。成为键空间。

 

 但其实这肯定不符合redis的设计思想嘛,我这么多KV都放着了,肯定是不现实的,键空间对于用户选择的数据库是相对应的也就是你选择的是1号数据库那是只会存储1号数据库里面的所有KV。

 

 当添加一个KV进入数据库的时候,Key是SDS,而Value可以是任何一个redisObject。如果是V是一个hashtable里面就还有有一个新的dict,ht[0],ht[1]什么的

删除的时候也是常规的思想,就是把这个KV从字典的引用中去除就行了。

更新的话根据不同的RedisObject会有不同的实现。

 

 取值的操作也是一样的,先从redisDb对象里面的dict找到key,然后再从redisObjetct中去获取value。如果是hashtale 的情况可以自己思考下,应该很容易就可以想明白了

在读写键空间的时候也会有很多额外的操作

1.读取键的时候,会根据这个value是否存在,然后更新键空间中的hit 或者 miss变量。

2.读取一个键的时候,会更新这个redisObject中的lru变量,从而更新时间

3.如果读取的时候发现这个键值对已经无效了,那么就会先删除这个key然后进行余下的操作

4.如果这个value被watch了,在修改的时候就会对这个键标记为脏

5.如果修改了一个键之后,会对这个键进行计数加一。方便后续的事物程序进行管理

6.如果开启了通知,那么就会发送对应的通知消息

 

给Key设置存活时间,这个也是在平时开发中经常使用到的东西,通过EXPIRE或者PEXPIRE命令来进行实现,SETEX和PEXPIRE的逻辑是一样的。TTL以及PTTL是返回剩余的存活时间。

在redisDb结构中还包含了一个expires字典,也就是过期字典,用来存储已经过期的Key和过期的时间

 

 至于如何进行删除,如果从资源分配的角度上思考,惰性删除是最好的,因为不用时时刻刻拉着一个线程进行。

 

 

 

 可以说惰性+定时的组合是最好的,针对业务进行时间上的choose

 

最后就是AOF和RDB了这个也是面试中很经常问到,一定要耐心。

在执行SAVE或者BGSAVE的时候,程序会对数据库里面的键进行check,已经过期的Key不会被保存到新建的RDB文件中。

在启动Redis服务器的时候(主服务器模式),会读取RDB中的文件,这时候也会对RDB中的数据进行check如果已经过期了就不会载入到数据库中去。如果是正常的服务器模式就会都载入进去。

如果服务器是以AOF进行运行的。当Key被过期的时候,就会想AOF中追加一条DEL命令,这个也可以看出在读取AOF是根据时间的有序性进行读取的。

在主从服务器架构中,当主服务器知道了一个key过期的时候 会向从服务器也发送一个DEL消息,让从服务器也去删除Key

从服务器遇到自身带的过期key的时候也会正常执行,从服务器只会对主服务器给的DEL消息进行执行。所以如果主从情况下,主节点一定一定要对过去的key可靠保证的发送消息。

数据库通知是2.8之后的新功能 没啥意思

 

posted @ 2020-12-17 15:13  smartcat994  阅读(121)  评论(0编辑  收藏  举报