Redis - 使用scan代替keys与hgetall操作
1.scan前言
當我們使用 keys * 或 hgetall 進行查詢的時候會進行堵塞,導致 redis 整體不可用(因為redis是單線程的),而使用 scan 命令則不會。
從Redis v2.8開始,SCAN命令已經可用,它允許使用游標從keyspace中檢索鍵。
對比KEYS命令,雖然SCAN無法一次性返回所有匹配結果,但是卻規避了阻塞系統這個高風險,從而也讓一些操作可以放在主節點上執行。
2.SCAN相關命令
- SCAN相關命令包括SSCAN 命令、HSCAN 命令和 ZSCAN 命令,分別用于集合、哈希鍵及有序集等
?
3.基本用法:
命令格式:
SCAN cursor [MATCH pattern] [COUNT count]
命令解釋:scan 游標 MATCH <返回和給定模式相匹配的元素> count 每次迭代所返回的元素數量
SCAN命令是增量的循環,每次調用只會返回一小部分的元素。所以不會有KEYS命令的坑(key的數量比較多,一次KEYS查詢會block其他操作)。 ?
SCAN命令返回的是一個游標,從0開始遍歷,到0結束遍歷。
通過scan中的MATCH <pattern> 參數,可以讓命令只返回和給定模式相匹配的元素,實現模糊查詢的效果
f
返回值解釋:
SCAN 命令、 SSCAN 命令、 HSCAN 命令和 ZSCAN 命令都返回一個包含兩個元素的 multi-bulk 回復:
- 回復的第一個元素是字符串表示的無符號 64 位整數(游標)
- 回復的第二個元素是另一個 multi-bulk 回復
4、注意
SCAN命令不能保證每次返回的值都是有序的,另外同一個key有可能返回多次,不做區分,需要應用程序去處理。
SCAN 命令返回的每個元素都是一個數據庫鍵。
SSCAN 命令返回的每個元素都是一個集合成員。
HSCAN 命令返回的每個元素都是一個鍵值對,一個鍵值對由一個鍵和一個值組成。
ZSCAN 命令返回的每個元素都是一個有序集合元素,一個有序集合元素由一個成員(member)和一個分值(score)組成。
5、Jedis實現
/*** @Description: 實現hscan dowhile形式* @Author: zongx* @Date: 2020/3/6* @Param: pattern* @return java.util.List<java.lang.String>*/public Map<String,String> hscan(final String key,final String pattern) {return execute(new JedisAction<Map<String,String>>() {@Overridepublic Map<String, String> action(Jedis jedis) {// 游標初始值為0String cursor = ScanParams.SCAN_POINTER_START;ScanParams scanParams = new ScanParams();scanParams.match(pattern);scanParams.count(Integer.MAX_VALUE);Map<String, String> results = new HashedMap();do {ScanResult<Map.Entry<String, String>> hscanResult =jedis.hscan(key, String.valueOf(cursor), scanParams);for (Map.Entry<String, String> en : hscanResult.getResult()) {results.put(en.getKey(),en.getValue());}//獲取游標位置,若大于0,則代表還有數據,需要繼續迭代cursor = hscanResult.getStringCursor();} while (Integer.parseInt(cursor) > 0);return results;}});}/***scan,while形式* @param pattern* @param count* @return*/public List<String> scan(final String pattern, final int count) {return execute(new JedisAction<List<String>>() {@Overridepublic List<String> action(Jedis jedis) {ScanParams params = new ScanParams();params.match(pattern);params.count(count);String cursor = "0";List<String> results = new ArrayList<>();while (true) {ScanResult scanResult = jedis.scan(cursor, params);List<String> elements = scanResult.getResult();if (elements != null && elements.size() > 0) {results.addAll(elements);}cursor = scanResult.getStringCursor();if ("0".equals(cursor)) {break;}}return results;}});}代碼還可以參考:
https://www.xttblog.com/?p=3635
工具類在下載中心可以下載
總結
以上是生活随笔為你收集整理的Redis - 使用scan代替keys与hgetall操作的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: db4o java教程_Db4o 社区版
- 下一篇: C#中Trim的功能介绍