Redis 集群中的键不能被删除(并且有空值)

Keys in Redis cluster cannot be deleted (and have empty value)

我们有一个 Redis 集群(3 master,3 slave),发现其中一个主节点(和相关的从节点)上有大量键,这些键似乎是空的,无法删除。

如果我连接到具有大量条目的主节点(由 DBSIZE 确定),我可以扫描并查看密钥:

--> redis-cli -h 192.168.100.81 -p 6381
192.168.100.81:6381> scan 0 match mykey-* count 10
1) "2359296"
2)  1) "mykey-1be333a7"
    2) "mykey-e85a9d31"
    3) "mykey-d9162eff"
    4) "mykey-41d12fd8"
    5) "mykey-a6e755d3"
    6) "mykey-c2aa1eaa"
    7) "mykey-c0597cac"
    8) "mykey-10e69376"
    9) "mykey-7263aef0"
   10) "mykey-7fa9de50"

但是,如果我尝试获取键的值,它会显示它已移动:

192.168.100.81:6381> get mykey-1be333a7
(error) MOVED 8301 192.168.3.107:6380

如果我连接到密钥已移动到的节点,我将无法获取或删除该值:

--> redis-cli -h 192.168.3.107 -p 6380
192.168.3.107:6380> get mykey-1be333a7
(nil)
192.168.3.107:6380> del mykey-1be333a7
(integer) 0

我也无法使用 redis-cli 的集群 (-c) 标志获取或删除值:

--> redis-cli -h 192.168.100.81 -p 6381 -c get mykey-1be333a7
(nil)
--> redis-cli -h 192.168.100.81 -p 6381 -c del mykey-1be333a7
(integer) 0
--> redis-cli -h 192.168.3.107 -p 6380 -c get mykey-1be333a7
(nil)
--> redis-cli -h 192.168.3.107 -p 6380 -c del mykey-1be333a7
(integer) 0

如何删除这些类型的密钥?

有趣的问题!

如何重现问题

以下是将重现您的问题的场景:

您创建了一个独立的 Redis 实例,并在其中设置了一些数据。但是,有一天,您将这个独立的 Redis 配置为 Redis 集群的成员,而无需刷新旧数据或将旧数据移动到集群的正确节点。我们称这些数据为脏数据。

在这种情况下,您可以扫描此实例上的所有键,包括脏数据。但是,您不能读取或写入这些脏数据,因为您的 Redis 处于集群模式,它会将您的请求重定向到正确的节点,该节点没有此类数据。

如何解决问题

为了删除这些脏数据,您应该将 Redis 实例重新配置为独立模式,即 cluster-enabled no,并在独立模式下删除脏数据。

然后就可以让它重新加入集群了