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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

Redis命令之hscan

發(fā)布時間:2023/12/14 数据库 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Redis命令之hscan 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1、業(yè)務(wù)背景

? ? ? 在互聯(lián)網(wǎng)的項目中為了提高性能和吞吐量,通常需要做一些優(yōu)化和數(shù)據(jù)異構(gòu),比如查詢DB,我們可以優(yōu)化索引,通過命中索引來提高查詢速度,也可以把數(shù)據(jù)異構(gòu)到Redis,雖然Redis的性能非常好也支持5種數(shù)據(jù)結(jié)構(gòu),如果想性能更好的話,可以考慮異構(gòu)到JVM緩存,也就是DB的數(shù)據(jù)異構(gòu)到Redis,Redis的數(shù)據(jù)定期異構(gòu)到JVM緩存

2、帶來問題

? ? 在Redis中通過用一個hashmap來存儲業(yè)務(wù)數(shù)據(jù),當(dāng)這些業(yè)務(wù)數(shù)據(jù)比較小,我們可以通過hGetAll來獲取redis的整個map然后設(shè)置到JVM緩存中,伴隨這業(yè)務(wù)的增長Redis中的key會非常多,這是我們調(diào)用hGetAll獲取數(shù)據(jù)時就會把Redis給hang住,造成整個redis阻塞,進(jìn)而影響整個redis集群的使用,導(dǎo)致其它業(yè)務(wù)調(diào)用redis時性能抖動

3、解決方案

? ? ? 1調(diào)整獲取命令hGetAll改成hscan,分階段獲取
? ? ? 2調(diào)整hash-max-ziplist-entries參數(shù)閾值由于調(diào)整改配置需要重新刷數(shù)據(jù)(不建議)

? ? ? ?我們采取方案1,通過HSCAN來迭代獲取對應(yīng)的值,通過指定游標(biāo)和獲取的數(shù)量,比如一次獲取10個,命令如下HSCAN key cursor [MATCH pattern] [COUNT count]? 它是一個增量式命令,每次查詢都是返回一部分?jǐn)?shù)據(jù),還可以通過它處理模糊查詢,所以不會像hGetAll類命令hang住Redis導(dǎo)致服務(wù)短暫停滯,最開始cursor我們都設(shè)置為0就好,count來控制每次遍歷的數(shù)量,由于這個命令執(zhí)行的時間復(fù)雜度是O(N),所以count越大,每次執(zhí)行時間理論上會越長,可以根據(jù)實際場景進(jìn)行調(diào)整,在遍歷時候判斷返回的游標(biāo)cursor是否為0,如果為0代表整個遍歷結(jié)束。

類似的命令如下:原理都一樣,都是避免把redis的進(jìn)場hang住,

  • SCAN?命令用于迭代當(dāng)前數(shù)據(jù)庫中的數(shù)據(jù)庫鍵。
  • SSCAN?命令用于迭代集合鍵中的元素。
  • HSCAN?命令用于迭代哈希鍵中的鍵值對。
  • ZSCAN?命令用于迭代有序集合中的元素(包括元素成員和元素分值)。

4、參考文檔

?http://doc.redisfans.com/key/scan.html#scan??

http://redisdoc.com/database/scan.html#scan

5、測試用例?

測試過程發(fā)現(xiàn)如果map集合的數(shù)據(jù)比較少,比如100個,雖然設(shè)置count只查10個,也會都返回過來?注意點:所有jimdb scan類操作,都要確保在一個副本

public Map<String,String> hScan(String key) {Map<String,String> allResult =new HashMap<>(1024);CallerInfo callerInfo = Profiler.registerInfo("CacheServicneire_hScan", O2nConstants.APP_NAME,false, true);try {ScanOptions scanOptions = ScanOptions.scanOptions().match("*").count(50).concurrent(1).build();ScanResult<Map.Entry<String, String>> scanResult = cluster.hScan(key,0,scanOptions);if(scanResult !=null && CollectionUtils.isNotEmpty(scanResult.getResult())){allResult.putAll(scanResult.getResult().stream().collect(Collectors.toMap(Entry::getKey,Entry::getValue)));while (scanResult.getCursor()>0){scanResult = cluster.hScan(key,scanResult.getCursor(), scanOptions);if(scanResult !=null && CollectionUtils.isNotEmpty(scanResult.getResult())){allResult.putAll(scanResult.getResult().stream().collect(Collectors.toMap(Entry::getKey,Entry::getValue)));}}}}catch (Exception e) {Profiler.functionError(callerInfo);log.error("執(zhí)行hScan操作失敗, key:{}", key, e);throw e;} finally {Profiler.registerInfoEnd(callerInfo);}return allResult;}

?

總結(jié)

以上是生活随笔為你收集整理的Redis命令之hscan的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。