Redis集群使用keys命令搜索匹配的Key

需求

今天在项目过程中碰到了一个需求:

1.所有节点(数量在1~10万)都会存储一个在线状态的Key在Redis集群,3分钟失效, 收到节点上报的任何数据后,刷新这个缓存。

2.需定时查询所有节点在Redis的状态,并将节点状态同步到数据库。

问题

因为Redis只有顶级的Key才可以设置超时时间,所以无法使用hset,hgetAll命令一次
性获取所有的节点信息,只有使用get(key)方法一个一个获取设备的在线状态,由于
Redis是单线程应用,这就造成了比较严重的性能问题。

经测试循环获取8万个节点的在线状态,耗时会达到50s左右,这是完全无法容忍的。

而项目中为保证可靠性,使用的是Redis集群,Redis操作都必须通过JedisCluster的
接口来实现,故而也无法使用Jedis的keys(pattern)方法来一次性搜索所有的在线节
点的Key。

解决思路

网络上搜索了一些解决方法,都感觉有些复杂,所以自己考虑是否可以用更简单的方
式解决这个问题。

思路是Redis集群有6个节点,其中有3个主节点,每个主节点各自有一个从节点,其
实只需要将集群视为3个单独的Redis,分别用keys(pattern)方法搜索各自的key,然
后把3次搜索的结果相加,就是集群内所有的Key了。

JedisCluster在网上的API很少,进去这个类看了一下,发现有一个方法:

Map getClusterNodes();
复制代码

根据方法名和返回值判断,这应该就是我要找的获取Redis集群所有节点的方法了,
写了个方法测试了一下,果然可以拿到集群内所有的节点,那剩下的事情就好办了。

最终的搜索集群内匹配的Key方法如下:

/**
 * 搜索集群内匹配的Key
 *
 * @param pattern 匹配规则,该参数和Jedis keys(pattern)方法相同。
 *                eg:搜索Node_status_开头的所有key,该参数填Node_status_*
 * @return 集群内所有符合规则的Key列表
 */
public Set clusterKeys(String pattern)throws DataLoadException{
    Set result = new HashSet<>();
    try {
        // 获取Redis集群内所有节点
        Map clusterNodes = jedisCluster.getClusterNodes();

        for (Map.Entry entry : clusterNodes.entrySet()) {
            Jedis jedis = entry.getValue().getResource();
            // 判断非从节点(因为若主从复制,从节点会跟随主节点的变化而变化)
            if (!jedis.info("replication").contains("role:slave")) {
                // 搜索单个节点内匹配的Key
                Set keys = jedis.keys(pattern);
                // 合并搜索结果
                result.addAll(keys);
            }
            jedis.close();
        }
    } catch (Exception e) {
        throw new DataLoadException(e);
    } finally {
        returnJedisCluster(jedisCluster);
    }
    return result;
}
复制代码

经测试,该方法一次性搜索8万个节点的在线状态,耗时在100ms左右。

你可能感兴趣的:(Redis集群使用keys命令搜索匹配的Key)