redis设计与实现-数据库

1.概述

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

默认情况下dbNum=16,所以Redis服务器默认会创建16个数据库。

默认情况下,redis客户端的目标数据库为0号数据库,客户端可以通过执行SELECT命令来切换数据库。

2.实现

源码:


struct redisServer {

    /* General */

    // 配置文件的绝对路径
    char *configfile;           /* Absolute config file path, or NULL */

    // serverCron() 每秒调用的次数
    int hz;                     /* serverCron() calls frequency in hertz */

    // 数据库
    redisDb *db;

    // 数据库个数
    int dbnum;         
    
    ...........
}



/* Redis database representation. There are multiple databases identified
 * by integers from 0 (the default database) up to the max configured
 * database. The database number is the 'id' field in the structure. */
typedef struct redisDb {

    // 数据库键空间,保存着数据库中的所有键值对
    dict *dict;                 /* The keyspace for this DB */

    // 键的过期时间,字典的键为键,字典的值为过期事件 UNIX 时间戳
    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 */

    // 正在被 WATCH 命令监视的键
    dict *watched_keys;         /* WATCHED keys for MULTI/EXEC CAS */

    struct evictionPoolEntry *eviction_pool;    /* Eviction pool of keys */

    // 数据库号码
    int id;                     /* Database ID */

    // 数据库的键的平均 TTL ,统计信息
    long long avg_ttl;          /* Average TTL, just for stats */

} redisDb;

例子:

3.生存/过期时间

3.1 设置过期时间

redis有四个不同的命令可以用于设置键的生存时间或者过期时间,四种命令最终执行效果都是使用pexpire实现的。

expire <key> <ttl> 将key的生存时间设置为ttl秒

pexpire <key> <ttl> 将key的生存时间设置为ttl毫秒

expireat  <key> <timestamp> 将key的过期时间设置为timestamp所指定的秒数时间戳

pexpireat  <key> <timestamp> 将key的过期时间设置为timestamp所指定的毫秒数时间戳

过期判断逻辑:

1.获取键的过期时间

2.键没有设置过期时间直接返回false

3.获取当前时间的unix时间戳

4.检查当前时间是否大于键的过去时间

4.1 如果是,返回true

4.2 如果否,返回false

3.2 过期key删除策略

先说说过期的策略有哪些:

1.定时删除:在创建key的同时,创建一个定时器,让定时器在过期时间的时候将key删除。

优点:尽快的删除过期的key,并释放内存

缺点:在过期key比较多的时候,过多的占用cpu资源

2.惰性删除:放任key过期不管,每次获取key的时候判断过期时间,过期了则删除。

优点:不会额外占用cpu资源

缺点:过期的key没有被删除,占用内存

3.定期删除:每个一段时间对数据库进行一次检查,删除过期的key。

相比1和2的方案,定期删除是一种折中方案。

定期时间间隔太短:占用cpu资源

定期时间间隔太长:过期的key没有被删除,占用内存

redis使用的策略是:2.惰性删除、3.定期删除

3.2.1 惰性删除策略的实现

所有读写数据库的redis命令执行之前都会调用db.c/expireIfNeeded函数进行检查。

3.2.3 定期删除策略的实现

过期key的定期删除策略由redis.c/activeExpireCycle实现,通过redis.c/serverCron定时触发。

1.activeExpireCycle每次执行都从一定数据库中取出一定数量的随机key进行检查,并删除过期的key。

2.全局变量current_db会记录activeExpireCycle的进度,下次触发就按照上一次的进度处理。

3.当所有的数据库都被执行一遍之后,current_db=0。然后开始下一轮检查。

4.AOF、RDB和复制功能对过期key的处理

4.1 RDB

在执行SAVE/BGSAVE生成RDB文件时,已经过期的key不会被保存到新创建的RDB文件里面。

在载入RDB文件的时候,如果是master服务器,会将过期的key过滤掉,slave服务器不管过不过期都会加载到数据库,等master服务器数据同步的时候在将过期的key删除。

4.1 AOF

如果key过期,但是没有被惰性和定期删除,不影响AOF文件写入,当key被惰性和定期删除时,程序会向AOF文件append一条DEL语句。

在执行AOF重写的时候,过期的key不会被写入AOF文件中。

4.2 主从复制

从服务器的过期key删除操作由主服务器控制,主服务器删除一个key的时候,会向所有服务器发送一个DEL命令;从服务在接口客户端读命令的时候,即使key过期也也不会做处理,只有接受到主服务器的DEL命令,才会删除过期key。

5.总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值