天天看點

redisCluster中模糊擷取key

在一個叢集中,顯然不能通過keys方法通過pattern直接擷取key的集合;鑒于這種問題,産生了兩種思路,如下:

方案1:已知相同的tag的KV會在一個節點上,是以隻要key帶有相同的hashtag,則會在一個節點上,是以隻要掃描該節點即可,這樣就将叢集轉化為了單點。

 @RequestMapping(value = "/ceshi", method = RequestMethod.GET)
    @ResponseBody
    public void Rediskeys() {
        /**
         * 模糊比對
         * @param pattern key的正規表達式
         * @param count 每次掃描多少條記錄,值越大消耗的時間越短,但會影響redis性能。建議設為一千到一萬
         * @return 比對的key集合
         */
        try{
            jedisCluster.getClusterNodes();
            ScanParams scanParams = new ScanParams();
            scanParams.match("{operatingSystem}*");
            scanParams.count(1000);
            ScanResult<String> result = jedisCluster.scan("0", scanParams);
            List<String> keyList = result.getResult();
            System.out.println("keyList======="+keyList);
        }finally{
        }
    }
           
//scanParams.match("*{zmc}*");//success
//scanParams.match("ZMC_text:{zmc}*");//success      

上述match方法中:括号中的參數也可以按照如上方式編寫;

其關鍵在于 key 上傳到redis中,命名方式裡面,必須含有 {};

并且{}前面、後面有無參數必須指定;若key為 ZMC_text: {zmc}:1  

scanParams.match("{zmc}*");查不出結果

方案2:擷取所有的節點,分别掃描每個節點,根據pattern擷取節點中的key,整合起來即可;

注意:cluster模式執行多key操作的時候,這些key必須在同一個slot上,不然會報JedisDataException異常;

@RequestMapping(value = "/ceshi3", method = RequestMethod.GET)
@ResponseBody
public void RedisKeys() {
    String redisKeyStartWith="Ad:ads:id:";
    try {
        Map<String, JedisPool> clusterNodes = jedisCluster.getClusterNodes();
        for (Map.Entry<String, JedisPool> entry : clusterNodes.entrySet()) {
            Jedis jedis = entry.getValue().getResource();
            // 判斷非從節點(因為若主從複制,從節點會跟随主節點的變化而變化)
            if (!jedis.info("replication").contains("role:slave")) {
                Set<String> keys = jedis.keys(redisKeyStartWith + "*");
                if (keys.size() > 0) {
                    Map<Integer, List<String>> map = new HashMap<>();
                    for (String key : keys) {
                        // cluster模式執行多key操作的時候,這些key必須在同一個slot上,不然會報:JedisDataException:
                        // CROSSSLOT Keys in request don't hash to the same slot
                        int slot = JedisClusterCRC16.getSlot(key);
                        // 按slot将key分組,相同slot的key一起送出
                        if (map.containsKey(slot)) {
                            map.get(slot).add(key);
                        } else {
                            map.put(slot, Lists.newArrayList(key));
                        }
                    }
                    for (Map.Entry<Integer, List<String>> integerListEntry : map.entrySet()) {
                        System.out.println("integerListEntry="+integerListEntry);
                        //jedis.del(integerListEntry.getValue().toArray(new String[integerListEntry.getValue().size()]));
                    }
                }
            }
        }
        logger.info("success redisKeys:{}", redisKeyStartWith);
    } finally {
    }
}
           

聲明:本文參考了 https://blog.csdn.net/u010416101/article/details/80754171  ;寫的很棒,可以參考一下...