zl程序教程

您现在的位置是:首页 >  数据库

当前栏目

你了解redis如何组织数据高效运行的吗?

Redis数据 如何 高效 运行 了解 组织
2023-06-13 09:15:19 时间

大家好,我是热心的大肚皮,皮哥。

之前我们聊过string、list、hash、set、zset,并且自实现了动态字符串、双端链表、hash字典、压缩链表、跳跃链表等结构。那么redis是怎么组织这些数据结构高效的运行呢?

redis如何新增一个kv

redis的键值都是redisObject对象,在创建时会生成redisDb中一个键名一个键值的redisObject对象。其中redisDb对象构成了redis的键空间。

键空间

redis是一个键值对(key-value pair)数据库服务器,服务器中的每个数据库都由一个redisDb结构表示,redisDb结构中dict字典保存了数据库中的所有键值对,我们将这个字典称为键空间(key space)。

typedef struct redisDb {
    // 保存着数据库以整数表示的号码
    int id;
    // 保存着数据库中的所有键值对数据
    // 这个属性也被称为键空间(key space)
    dict *dict;
    // 保存着键的过期信息
    dict *expires;
    // 实现列表阻塞原语,如 BLPOP
    dict *blocking_keys;
    dict *ready_keys;
    // 用于实现 WATCH 命令
    dict *watched_keys;
} redisDb;

redisObject

每一个redis中key的value都是下面的结构。

typedef struct redisObject {
    // 类型
    unsigned type:4;
    // 编码
    unsigned encoding:4;
    // 指向数据的指针
    void *ptr;
    // 记录对象最后一次被程序访问时间,用于计算空转时长(当前时间-lru)
    unsigned lru:22; /* lru time (relative to server.lruclock) */
    // 引用计数,用于内存回收
    int refcount;
} robj;

如图所示:

大家看到这里应该明白了吧,具体的添加如下图。

  • 在键空间中根据hash算法查询新增加的key是否存在。
  • 不存在则进行新增。

修改与删除区别不大,就不过多阐述了。

redis如何过期一个kv

过期字典

在键空间中,不单单有dict字典,还有个expires属性,这个expires字典记录着当前数据库的全部过期时间,也叫做过期字典:

  • 过期字典的键是一个指针,指向某个对象。
  • 过期字典的值是一个long类型的整数。

其中过期字典与正常的键都指向同一个对象,所以不存在空间浪费。

过期策略

我们推断一下过期策略可能有三种。

  • 定时过期:在设置key时,同时创建一个定时器,在key过期的时候,执行key的删除操作。
  • 惰性过期:在每次查询时,判断是否过期,过期则进行删除。
  • 定期过期:每隔一段时间,对数据库进行检查,删除其中的过期key。

定时过期,在redis中创建大量的定时器,太消耗性能,而惰性过期,如果key不被访问,那么会浪费大量的内存,定期过期则会造成过期的数据也被访问到。为了解决上面的问题,redis采用惰性过期与定期过期一起使用

惰性过期具体流程如下。

而定期过期由activeExpireCycle函数实现,每当serverCron函数执行时,activeExpireCycle函数会在规定时间内分多次遍历各个数据库,在过期字典里随机检查一部分key的过期时间并删除,

  • 默认是每个库随机检查20个key,扫描时间上限25ms。
  • 删除这个20个过期的key。
  • 如果过期的比例超过4分之1,则重复删除。

工作小技巧

假设一个大型的redis集群中,大量的key同时过期了,会出现什么样的结果呢?之前皮哥接手了一个电商某模块的C端系统后,通过性能监控发现每天一个固定的时间,用到的redis的接口都会出现性能抖动,可用率降低。

经过分析发现,是在同一时间有大量的key过期,从而导致性能波动,那么为什么会出现这种原因呢?原因有二。

  • redis在过期key的时候,会多次扫描过期字典,直到过期key变得稀疏后,才会停止。
  • 内存管理器需要频繁回收内存页,会产生cpu消耗。

如果在过期时客户端请求过来,而客户端的超时时间设置的比较短,那么会出现大量的链接超时断开,业务会出现很多异常。所以一定要注意,解起来也比较简单,可以在过期时间上加个随机数来避免,这样也能让你的TL对你刮目相看呦。