我在 Golang 中使用 scan 命令,根据提供的模式获取 Redis 键。我使用的是 Redis 集群,因此为了避免键丢失,我使用了 ForEachMaster。以下是我使用的代码:
func deleteCacheKeys(ctx context.Context, pattern string, count int64, retries int) error {
redisClient := redis.NewClusterClient(&redis.ClusterOptions{
Addrs: []string{redisCluster},
})
if err := redisClient.Ping(ctx).Err(); err != nil {
return err
}
var cursor uint64
err = redisClient.ForEachMaster(ctx, func(ctx context.Context, nodeClient *redis.Client) error {
for {
keys, cursor := nodeClient.Scan(ctx, cursor, pattern, count).Val()
if len(keys) > 0 {
cmd := nodeClient.Del(ctx, keys...)
if cmd.Err() != nil {
return cmd.Err()
}
}
if cursor == 0 {
break
}
}
return nil
})
return err
}
在这个函数中,棘手的部分在于每个节点客户端扫描命令中使用的计数。当我将其设置为 1000000 时,一切正常。但是当我使用更低的数值,例如 100 甚至 100000 时,这段代码就会陷入无限循环(我等待的最长时间是 30 分钟)。当使用 1000000 作为计数时,删除模式通常需要几秒钟的时间。
之前我们用 100 万个数据都没问题,直到我们的 Redis 数据集变得非常大,这个数量也引发了无限循环。我目前正在寻找一种安全的方法来删除这些模式,而不用担心这个数量。我真的很想知道为什么会发生这种情况。
我试过把它设置为 -1,但还是卡住了。我也试过用 Unlink 代替 Del 命令,但结果还是一样。