阅读 18

《Redis设计与实现》读书笔记(七)数据库

本文主要关于:

redis数据库实现的介绍
前面介绍的各种数据,在redis服务器中的内存模型是什么样的的。
RDB文件将这些内存数据持久化后的格式是什么样的
RDB和AOF序列化的区别是什么
redis提供什么机制保障AOF文件不会一直增长
RDB文件转储成json文件和内存分析工具介绍
客户端和服务端数据结构介绍

数据库

服务器的数据库

redis是内存型数据库,所有数据都放在内存中
保存这些数据的是redisServer这个结构体,源码中该结构体包括大概300多行的代码。具体参考server.h/redisServer
和数据库相关的两个属性是:

int类型的dbnum:表示数据库数量,默认16个
redisDb指针类型的db:数据库对象数组

数据库对象 所在文件为server.h。数据库中所有针对键值对的增删改查,都是对dict做操作

typedef struct redisDb {
    dict *dict;                 /* The keyspace for this DB  */
    dict *expires;              /* Timeout of keys with a timeout set */
    dict *blocking_keys;        /* Keys with clients waiting for data (BLPOP)*/
    dict *ready_keys;           /* Blocked keys that received a PUSH */
    dict *watched_keys;         /* WATCHED keys for MULTI/EXEC CAS */
    int id;                     /* Database ID */
    long long avg_ttl;          /* Average TTL, just for stats */
} redisDb;
复制代码

dict:保存了该数据库中所有的键值对,键都是字符串,值可以是多种类型
expires:保存了该数据中所有设置了过期时间的key
blocking_keys:保存了客户端阻塞的
watched_keys:保存被watch的命令
id:保存数据库索引
avg_ttl

客户端切换数据库

客户端通过select dbnum 命令切换选中的数据库
客户端的信息保存在client这个数据结构中,参考server.h/client
client的类型为redisDb的db指针指向目前所选择的数据库

读写键空间时的其他操作

读写键空间时,是针对dict做操作,但是除了完成基本的增改查找操作,还会执行一些额外的维护操作,包括:

读写键时,会根据是否命中,更新hit和miss次数。

相关命令:info stats keyspace_hits, info stats keyspace_misses  
复制代码

读取键后,会更新键的LRU时间,前面章节介绍过该字段
读取时,如果发现键已经过期,会先删除该键,然后才执行其他操作
如果watch监视了某个键,修改时会标记该键为脏(dirty)
每修改一个键,会对脏键计数器加1,触发持久化和复制操作
如果开启通知功能,修改键会下发通知

设置过期时间

expire key ttl:设置生存时间为ttl秒
pexpire key ttl:设置生存时间为ttl毫秒
expireat key timestamp:设置过期时间为timstamp的秒数时间戳
pexpireat key timestamp:过期时间为毫秒时间戳
persist key:解除过期时间
ttl key:获取剩余生存时间

保存过期时间

过期时间保存在expires的字典中,值为long类型的毫秒时间戳

过期键删除策略

各种删除策略的对比

策略类型 描述 优点 缺点 redis是否采用
定时删除 通过定时器实现 保证过期键能尽快释放 对cpu不友好,影响相应时间和吞吐量
惰性删除 放任不管,查询时才去检查 对cpu友好 没有被访问的永远不会被释放,相当于内存泄露
定期删除 每隔一段时间检查 综合前面的优点 难于确定执行时长和频率

redis使用的过期键删除策略

redis采用了惰性删除和定期删除策略

惰性删除的实现

由db.c中的expireIfNeeded实现
每次执行redis命令前都会调用该函数对输入键做检查

定期删除的实现

server.c中的serverCron函数执行定时任务
函数每次运行时,都从一定数量的数据库中取出一定数量的键进行检查,并删除过期键

数据库通知

键空间通知:客户端获取数据库中键执行了什么命令。 实现代码为notify.c文件的notifyKeyspaceEvent函数subscribe keyspace@0:keyname

键事件通知:某个命令被什么键执行了subscribe keyevent@0:del

关注下面的标签,发现更多相似文章
评论