Redis命令之hscan

Redis命令之hscan1 业务背景在互联网的项目中为了提高性能和吞吐量 通常需要做一些优化和数据异构 比如查询 DB 我们可以优化索引 通过命中索引来提高查询速度 也可以把数据异构到 Redis 虽然 Redis 的性能非常好也支持 5 种数据结构 如果想性能更好的话 可以考虑异构到 JVM 缓存 也就是 DB 的数据异构到 Redis Redis 的数据定期异构到 JVM 缓存 2 带来问题在 Redis 中通过用一个 hashmap 来存储业务数据 当这些业务数据比较小 我们可以通过 hGetAll 来获取 redis 的整个 map 然后设

1、业务背景

      在互联网的项目中为了提高性能和吞吐量,通常需要做一些优化和数据异构,比如查询DB,我们可以优化索引,通过命中索引来提高查询速度,也可以把数据异构到Redis,虽然Redis的性能非常好也支持5种数据结构,如果想性能更好的话,可以考虑异构到JVM缓存,也就是DB的数据异构到Redis,Redis的数据定期异构到JVM缓存

2、带来问题

    在Redis中通过用一个hashmap来存储业务数据,当这些业务数据比较小,我们可以通过hGetAll来获取redis的整个map然后设置到JVM缓存中,伴随这业务的增长Redis中的key会非常多,这是我们调用hGetAll获取数据时就会把Redis给hang住,造成整个redis阻塞,进而影响整个redis集群的使用,导致其它业务调用redis时性能抖动

3、解决方案

       我们采取方案1,通过HSCAN来迭代获取对应的值,通过指定游标和获取的数量,比如一次获取10个,命令如下HSCAN key cursor [MATCH pattern] [COUNT count]  它是一个增量式命令,每次查询都是返回一部分数据,还可以通过它处理模糊查询,所以不会像hGetAll类命令hang住Redis导致服务短暂停滞,最开始cursor我们都设置为0就好,count来控制每次遍历的数量,由于这个命令执行的时间复杂度是O(N),所以count越大,每次执行时间理论上会越长,可以根据实际场景进行调整,在遍历时候判断返回的游标cursor是否为0,如果为0代表整个遍历结束。

类似的命令如下:原理都一样,都是避免把redis的进场hang住,

  • SCAN 命令用于迭代当前数据库中的数据库键。
  • SSCAN 命令用于迭代集合键中的元素。
  • HSCAN 命令用于迭代哈希键中的键值对。
  • ZSCAN 命令用于迭代有序集合中的元素(包括元素成员和元素分值)。

4、参考文档

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

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

5、测试用例 

测试过程发现如果map集合的数据比较少,比如100个,虽然设置count只查10个,也会都返回过来 注意点:所有jimdb scan类操作,都要确保在一个副本

 public Map 
  
    hScan(String key) { Map 
   
     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 
    
      > 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("执行hScan操作失败, key:{}", key, e); throw e; } finally { Profiler.registerInfoEnd(callerInfo); } return allResult; } 
     
    
  

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/221356.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 下午6:18
下一篇 2026年3月17日 下午6:19


相关推荐

  • 菜鸟开发—应具备的搜索技巧[通俗易懂]

    菜鸟开发—应具备的搜索技巧

    2022年1月25日
    46
  • java webservice服务端和客户端创建(JAX-WS)[通俗易懂]

    java webservice服务端和客户端创建(JAX-WS)[通俗易懂]idea:2020jdk:1.8目录1.搭建webservice服务端1.1新建一个java空项目1.2项目建好后,右键项目,选择“AddFrameworkSupport…”1.3生成wsdl,右键类的时候可能没有WebServices这个选项了,可以在Tools中找到这个功能1.4启动服务,右键HelloWorld启动项目1.5访问web服务1.6增加一个方法看看效果2.搭建webservice客户端2.1新建一个java空项目2.2项目生成好后会弹框出来,把wsdl地址放

    2022年7月13日
    23
  • 怎么获取smtp服务器用户帐号和密码

    怎么获取smtp服务器用户帐号和密码

    2022年3月3日
    55
  • 京东静态网页设计案例(1)

    京东静态网页设计案例(1)一、准备步骤以京东网页为设计案例,使用HTML和CSS进行设计,首先要在头部&lt;head&gt;文件中加入&lt;link&gt;对CSS文件里加入的两个CSS代码文件进行链接,一个是设置格式的代码,另一个是下载的图标库代码。示例代码如下:&lt;linkrel="stylesheet"href="./css/index.css"/&gt;&lt;linkrel="s…

    2025年9月12日
    7
  • 高斯白噪声(white Gaussian noise,WGN)

    高斯白噪声(white Gaussian noise,WGN)高斯白噪声(whiteGaussiannoise,WGN)

    2025年7月24日
    5
  • 图像修复 python_50.图像修复

    图像修复 python_50.图像修复目标本节主要学习内容 使用图像修复技术去除照片中的噪声和划痕 掌握 OpenCV 中与图像修复技术相关的函数基础说明想一想 你在生活中有没有遇到过这样的问题 一张自己很喜欢的具有怀念意义的照片 随着年代的久远 照片逐渐老化 有时候在看照片时一不小心弄上了点污渍或者是画了几笔 你有没有想过要修复这些照片呢 你可能会说 我可以使用笔刷工具简易在上面涂抹两下不就行了吗 但这其实是没用的 事实上你只

    2026年3月19日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号