关于redis:Redis之object-idletime为什么是不可靠的

问题引入

  Redis是一款基于内存的key-value数据库,内存使用率是咱们十分关注的一个指标。

  通常咱们都能够通过『EXPIRE key seconds』等形式,为指定键设置生存工夫;待过期后,Redis会主动删除该键值对,以此避免内存应用持续增长。

  然而,生产环境中,往往存在很多键值对都没有设置正当的生存工夫;随着业务的继续倒退,内存使用量也持续增长。

  DBA或者研发人员,在监控到Redis占用内存过高时,能够手动清理某些长期不拜访的键值对。如何判断一个键值对多久没有被拜访了呢?能够通过命令object idletime实现,该命令返回的是以后键从上一次拜访到当初通过的工夫(单位,秒):

127.0.0.1:6379> object idletime key
(integer) 2

  在一次统计过程中,发现有一批key曾经很长时间没有拜访了(数月),然而object idletime命令却表明最近刚被拜访过(甚至数秒内)。

  为什么会不准呢?为此钻研了下object idletime的实现原理。

object idletime实现

  Redis外部对象应用构造体redisObject示意,其定义为:

typedef struct redisObject {
    //数据类型,string,list,hash等
    unsigned type:4;
    //编码,即底层采纳哪种数据结构
    unsigned encoding:4;
    
    //缓存淘汰应用;会存储上一次该对象的拜访工夫
    unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or
                            * LFU data (least significant 8 bits frequency
                            * and most significant 16 bits access time). */
    //援用计数
    int refcount;
    //指向对应的数据结构
    void *ptr;
} robj;

  能够看到,正因为redisObject.lru字段的存在,咱们才能够获取到任何一个对象的闲暇工夫,以后工夫 – 上次访问工夫lru,即可。

  object命令的实现函数为objectCommand。

objectCommand(client *c) 
    objectCommandLookupOrReply(client *c, robj *key, robj *reply)
        objectCommandLookup(client *c, robj *key)
        
robj *objectCommandLookup(client *c, robj *key) {
    dictEntry *de;

    if ((de = dictFind(c->db->dict,key->ptr)) == NULL) return NULL;
    return (robj*) dictGetVal(de);
}

  objectCommandLookup函数返回的是该键值对的值,即最终是根据key-value值对象的lru计算的。

  值对象有什么非凡吗?Redis外部的对象在某些状况下是能够共享的,比方整数。

#define OBJ_SHARED_INTEGERS 10000

struct sharedObjectsStruct {
    //共享的整数对象
    *integers[OBJ_SHARED_INTEGERS],
};


set keya 1
set keyb 1
set keyc 1

  因而,上述命令执行后,keya、keyb以及keyc对应的值是同一个对象。而当咱们拜访keyc键时,其对应值对象的lru会更新,导致object idletime查问到的keya与keyb的闲暇工夫随之扭转。

127.0.0.1:6379> object idletime keya
(integer) 1302
127.0.0.1:6379> set keyb 1
OK
127.0.0.1:6379> get keyb
"1"
127.0.0.1:6379> object idletime keya
(integer) 4

  业务中很多时候设置key-value只是设置一个标识,value都为数字1等(比方通过setnx实现锁),这就导致大量的键对应的值对象关联起来,object idletime随之也相互影响。

论断

  当多个键的值是一些简略整数时,他们共享同一个值对象,而object idletime命令返回的是值对象的闲暇工夫,就导致这些键的object idletime相互影响。在应用object idletime统计键的闲暇工夫,须要特地留神这一点。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理