在redis slave上由info命令列出的过期密钥数量与我看到的不一致

时间:2017-08-23 16:25:32

标签: redis

当我在info中针对redis 3.2.4服务器运行redis-cli命令时,它会显示此信息已过期:

expires=223518

但是,当我运行keys *命令并为每个密钥请求ttl时,只打印出带有ttl>键的密钥。 0,我只看到几百个。

我认为expires是过期密钥数量的计数,但我甚至不在这个数字的数量级内。

有人可以准确澄清expires的意思吗?这是否包括待过期和先前已过期但尚未驱逐的密钥?

更新:

以下是我计算过期密钥数量的方法:

  task count_tmp_keys: :environment do
    redis = Redis.new(timeout: 100)
    keys = redis.keys '*'
    ct_expiring = 0

    keys.each do |k|
      ttl = redis.ttl(k)
      if ttl > 0
        ct_expiring += 1
        puts "Expiring: #{k}; ttl is #{ttl}; total: #{ct_expiring}"
        STDOUT.flush
      end
    end

    puts "Total expiring: #{ct_expiring}"
    puts "Done at #{Time.now}"
  end

当我运行此脚本时,它显示我的总到期时间为78

当我运行信息时,它会显示db0:keys=10237963,expires=224098,avg_ttl=0

因为224098比78大得多,所以我很困惑。有没有更好的方法让我获得所有225k到期密钥的列表?

另外,我的平均ttl是0是多少?你不期望它是非零的吗?

更新

我在本地获得了新信息和简单的100%责备这种情况!

要复制:在笔记本电脑上本地设置两个redis进程。让一个成为另一个的奴隶。在从属进程中,设置以下内容:

config set slave-serve-stale-data yes
config set slave-read-only no

现在,连接到从站(不是主站)并运行:

set foo 1
expire foo 10

10秒后,您将无法再访问foo,但info命令仍会显示您的1个密钥到期,平均ttl为0。

有人可以解释这种行为吗?

2 个答案:

答案 0 :(得分:2)

expires只返回将过期的密钥大小。

3.2.4的source code

long long keys, vkeys;

keys = dictSize(server.db[j].dict);
vkeys = dictSize(server.db[j].expires);
if (keys || vkeys) {
    info = sdscatprintf(info,
        "db%d:keys=%lld,expires=%lld,avg_ttl=%lld\r\n",
        j, keys, vkeys, server.db[j].avg_ttl);
}

它只计算server.db[j].expires的大小。 (注意j是数据库索引)。

答案 1 :(得分:1)

expires包含现有的TTL密钥,该密钥将过期,不包括已过期的密钥。 示例(为简洁起见,遗漏了info命令中的额外信息):

127.0.0.1:6379> flushall
OK
127.0.0.1:6379> SETEX mykey1 1000 "1"
OK
127.0.0.1:6379> SETEX mykey2 1000 "2"
OK
127.0.0.1:6379> SETEX mykey3 1000 "3"
OK
127.0.0.1:6379> info
# Keyspace
db0:keys=3,expires=3,avg_ttl=992766
127.0.0.1:6379> SETEX mykey4 1 "4"
OK
127.0.0.1:6379> SETEX mykey5 1 "5"
OK
127.0.0.1:6379> info
# Keyspace
db0:keys=3,expires=3,avg_ttl=969898
127.0.0.1:6379> keys *
1) "mykey2"
2) "mykey3"
3) "mykey1"
127.0.0.1:6379> 

鉴于在您的情况下,您询问奴隶的密钥到期,按https://github.com/antirez/redis/issues/2861

  奴隶上的

键没有主动过期,因此avg_ttl是   从未计算过

根据https://groups.google.com/forum/#!topic/redis-db/NFTpdmpOPnc

  

avg_ttl永远不会在奴隶上初始化,因此它可以是永远的   任意值驻留在那个地方的内存中。

因此,可以预期info命令在从属上的行为不同。