日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

Redis - 使用scan代替keys与hgetall操作

發布時間:2023/12/14 数据库 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Redis - 使用scan代替keys与hgetall操作 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.scan前言

當我們使用 keys * 或 hgetall 進行查詢的時候會進行堵塞,導致 redis 整體不可用(因為redis是單線程的),而使用 scan 命令則不會。

從Redis v2.8開始,SCAN命令已經可用,它允許使用游標從keyspace中檢索鍵。
對比KEYS命令,雖然SCAN無法一次性返回所有匹配結果,但是卻規避了阻塞系統這個高風險,從而也讓一些操作可以放在主節點上執行。

2.SCAN相關命令

  • SCAN相關命令包括SSCAN 命令、HSCAN 命令和 ZSCAN 命令,分別用于集合、哈希鍵及有序集等
  • SCAN 命令用于迭代當前數據庫中的數據庫鍵。
  • SSCAN 命令用于迭代集合鍵中的元素。
  • HSCAN 命令用于迭代哈希鍵中的鍵值對。
  • ZSCAN 命令用于迭代有序集合中的元素(包括元素成員和元素分值)。
  • 因為 SCAN 、 SSCAN 、 HSCAN 和 ZSCAN 四個命令的工作方式都非常相似, 要記住:SSCAN 命令、 HSCAN 命令和 ZSCAN 命令的第一個參數總是一個數據庫鍵。而 SCAN 命令則不需要在第一個參數提供任何數據庫鍵 —— 因為它迭代的是當前數據庫中的所有數據庫鍵。

    ?

    3.基本用法:

    命令格式:

    SCAN cursor [MATCH pattern] [COUNT count]


    命令解釋:scan 游標 MATCH <返回和給定模式相匹配的元素> count 每次迭代所返回的元素數量


    SCAN命令是增量的循環,每次調用只會返回一小部分的元素。所以不會有KEYS命令的坑(key的數量比較多,一次KEYS查詢會block其他操作)。 ?
    SCAN命令返回的是一個游標,從0開始遍歷,到0結束遍歷。
    通過scan中的MATCH <pattern> 參數,可以讓命令只返回和給定模式相匹配的元素,實現模糊查詢的效果

    示例: scan 0 match DL* count 5 sscan myset 0 match f*

    f

    返回值解釋:

    SCAN 命令、 SSCAN 命令、 HSCAN 命令和 ZSCAN 命令都返回一個包含兩個元素的 multi-bulk 回復

    • 回復的第一個元素是字符串表示的無符號 64 位整數(游標)
    SCAN 命令每次被調用之后, 都會向用戶返回一個新的游標, 用戶在下次迭代時需要使用這個新游標作為 SCAN 命令的游標參數, 以此來延續之前的迭代過程。 當 SCAN 命令的游標參數被設置為 0 時, 服務器將開始一次新的迭代, 而當服務器向用戶返回值為 0 的游標時, 表示迭代已結束。
    • 回復的第二個元素是另一個 multi-bulk 回復
    這個 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操作的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。