• Redis 设计与实现 1:数据库 redisDb


    服务器中的数据库

    Redis 服务器将绝大部分的信息都保存在 server.h/redisServer。redis 的数据是保存在 redisServer 中的 redisDb 结构中。

    struct redisServer {
        // ...
        redisDb *db; // 数据库列表
        // ...
        int dbnum;   // 数据库数量
        // ...
    }
    
    • db 中每个redisDb结构代表一个数据库。
    • 在初始化服务器时,程序会根据服务器状态的 dbnum 属性来决定应该创建多少个数据库。
    • dbnum 属性的值由服务器配置的 database 选项决定,默认情况下,该选项的值为16,所以Redis服务器默认会创建16个数据库。

    数据库键空间

    Redis 是一个键值对数据库服务器,服务器中的每个数据库都由一个 server.h/redisDb 结构表示.
    其中,redisDbdict 字典属性保存了数据库中的所有键值对,我们将这个字典称为键空间(key space):

    typedef struct redisDb {
        dict *dict; 
        // ...
    } redisDb;
    

    dict 中的数据跟我们平常操作的键值对是一一对应的:

    • dict 的 key 就是数据库中的 key,字符串类型
    • dict 的 值 就是数据库中的 值,这个值可以是 stringhashzsetsetlist 中的任何一种

    示例

    如果我们在数据库中,执行以下命令:

    redis > SET str_key str_value
    OK
    redis > RPUSH list_key a b c
    (integer) 3
    

    新添加的两个 key 的结构如下图所示:

    RedisDb 结构示例

    从上面的示例图可以很清晰地知道 Redis 数据是如何组织的,增删改查也就是对 dict 的操作而已,此处就不详细说了。

    Key 的过期时间

    1. 数据结构

    redisDb 中的 expires 属性保存了所有 key 的过期时间,我们姑且就称它为过期字典吧。

    • 过期字典中的键,是一个指针,指向了真实数据的 key,不会浪费空间多保存一次
    • 过期字典中的值,存的是具体的过期时间点,精确到毫秒的时间戳
    typedef struct redisDb {
        // ...
        // 保存了所有 key 的过期时间
        dict *expires; 
        // ...
    } redisDb;
    

    命令TTLPTTL 都是去查这个过期字典的过期时间,然后减去当前时间,得到的就是剩余的时间啦。

    2. 过期 key 的删除策略

    一个 key 过期时间到了之后,是如何进行删除的呢?Redis 使用了一下两种策略:惰性删除、定期删除

    惰性删除

    惰性删除策略指的是:key 在过期之后,没有立即删除,而是在读写 key 的时候,才对过期的 key 进行删除。
    代码实现在 db.c/expireIfNeeded 方法中。所有 key 的读写之前,都会先调用 expireIfNeeded 对 key 进行检查,如果已过期,则删除。

    定期删除

    定期删除策略指的是:Redis 每隔一段时间,随机从数据库中取出一定量的 key 进行检查,如果已过期,则进行删除。
    代码实现在 expire.c/activeExpireCycle 方法中。

    删除的步骤:

    1. 从过期字典中随机 20 个 key
    2. 删除这 20 个 key 中已经过期的 key
    3. 如果过期的 key 比率超过 1/4,那就重复步骤 1

    为什么只是随机挑 一些 key 呢?因为如果把所有 key 都遍历一遍,那这个性能肯定是不能接受的!所以还需要配合 惰性删除。

    本文的分析没有特殊说明都是基于 Redis 6.0 版本源码
    redis 6.0 源码:https://github.com/redis/redis/tree/6.0

  • 相关阅读:
    bzoj 3876: [Ahoi2014&Jsoi2014]支线剧情【有上下界有源汇最小费用最大流】
    bzoj 2055: 80人环游世界【有上下界有源汇最小费用最大流】
    bzoj 2406: 矩阵【二分+有源汇上下界可行流】
    bzoj 4873: [Shoi2017]寿司餐厅【最大权闭合子图】
    bzoj 2007: [Noi2010]海拔【最小割+dijskstra】
    bzoj 2039: [2009国家集训队]employ人员雇佣【最小割】
    bzoj 3996: [TJOI2015]线性代数【最小割】
    bzoj 3158: 千钧一发【最小割】
    bzoj 2597: [Wc2007]剪刀石头布【最小费用最大流】
    bzoj 5120: [2017国家集训队测试]无限之环【最小费用最大流】
  • 原文地址:https://www.cnblogs.com/chenchuxin/p/14187898.html
Copyright © 2020-2023  润新知