SpringBoot3 + Jedis5 + Redis集群 如何通过scan方法分页获取所有keys

背景:

由于需要升级老项目代码,从SpringBoot1.5.x 升级到 SpringBoot3.3.x,框架中引用的Jedis自动升级到了 5.x;正好代码中有需要获取Redis集群的所有keys的需求存在;代码就不适用了,修改如下:

POM

由于默认是lettuce,需要手动添加jedis客户端

       <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><exclusions><!-- 不依赖Redis的异步客户端lettuce --><exclusion><groupId>io.lettuce</groupId><artifactId>lettuce-core</artifactId></exclusion></exclusions></dependency><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId></dependency>

Jedis3.x写法

   public Set<String> keys(String pattern) {Set<String> set = new HashSet<>();JedisClusterConnection jedisClusterConnection = (JedisClusterConnection) redisTemplate.getConnectionFactory().getClusterConnection();//这里是获取jedispool的另外一种方式与上边的pipline可以对比下,两种方式都可以实现Map<String, JedisPool> clusterNodes = jedisClusterConnection.getNativeConnection().getClusterNodes();for (Map.Entry<String, JedisPool> entry : clusterNodes.entrySet()) {//获取单个的jedis对象Jedis jedis = entry.getValue().getResource();// 判断非从节点(因为若主从复制,从节点会跟随主节点的变化而变化),此处要使用主节点, 从主节点获取数据if (!jedis.info("replication").contains("role:slave")) {Set<String> keys = getScan(jedis, pattern);if (keys.size() > 0) {Map<Integer, Set<String>> map = new HashMap<>(8);//接下来的循环不是多余的,需要注意for (String key : keys) {// cluster模式执行多key操作的时候,这些key必须在同一个slot上,不然会报:JedisDataException:int slot = JedisClusterCRC16.getSlot(key);// 按slot将key分组,相同slot的key一起提交if (map.containsKey(slot)) {map.get(slot).add(key);} else {Set<String> set1 = new HashSet<>();set1.add(key);map.put(slot, set1);}}for (Map.Entry<Integer, Set<String>> integerListEntry : map.entrySet()) {set.addAll(integerListEntry.getValue());}}}}return set;}@SuppressWarnings({ "rawtypes", "unchecked" })public Set<String> getScan(Jedis jedis, String key) {Set<String> set = new HashSet<>();//扫描的参数对象创建与封装ScanParams params = new ScanParams();params.match(key);//扫描返回一百行,这里可以根据业务需求进行修改params.count(1000);String cursor = "0";ScanResult scanResult = jedis.scan(cursor, params);//scan.getStringCursor() 存在 且不是 0 的时候,一直移动游标获取while (null != scanResult.getCursor()) {//封装扫描的结果set.addAll(scanResult.getResult());if (!"0".equals(scanResult.getCursor())) {scanResult = jedis.scan(scanResult.getCursor(), params);} else {break;}}return set;}

Jedis5.x写法

    /*** 获取符合条件的key* @param pattern 表达式* @return*/public Set<String> keys(String pattern) {Set<String> set = new HashSet<>();JedisClusterConnection jedisClusterConnection = (JedisClusterConnection) redisTemplate.getConnectionFactory().getClusterConnection();//这里是获取jedispool的另外一种方式与上边的pipline可以对比下,两种方式都可以实现Map<String, ConnectionPool> clusterNodes = ((JedisCluster) jedisClusterConnection.getNativeConnection()).getClusterNodes();// 看源码获取 key就是 host:port格式Set<String> nodes = clusterNodes.keySet();for (String node : nodes) {HostAndPort nodeObj = HostAndPort.from(node);try (Jedis jedis = new Jedis(nodeObj.getHost(), nodeObj.getPort())) { // try-with-resources可以自动关闭资源String roleInfo = jedis.info("replication");if (roleInfo.contains("role:master")) {Set<String> keys = getScan(jedis, pattern);if (keys.size() > 0) {Map<Integer, Set<String>> map = new HashMap<>(8);//接下来的循环不是多余的,需要注意for (String key : keys) {// cluster模式执行多key操作的时候,这些key必须在同一个slot上,不然会报:JedisDataException:int slot = JedisClusterCRC16.getSlot(key);// 按slot将key分组,相同slot的key一起提交if (map.containsKey(slot)) {map.get(slot).add(key);} else {Set<String> set1 = new HashSet<>();set1.add(key);map.put(slot, set1);}}for (Map.Entry<Integer, Set<String>> integerListEntry : map.entrySet()) {set.addAll(integerListEntry.getValue());}}}} catch (Exception e) {logger.error("redis连接错误:", e);}}return set;}@SuppressWarnings({ "rawtypes", "unchecked" })public Set<String> getScan(Jedis jedis, String key) {Set<String> set = new HashSet<>();//扫描的参数对象创建与封装ScanParams params = new ScanParams();params.match(key);//扫描返回一百行,这里可以根据业务需求进行修改params.count(1000);String cursor = "0";ScanResult scanResult = jedis.scan(cursor, params);//scan.getStringCursor() 存在 且不是 0 的时候,一直移动游标获取while (null != scanResult.getCursor()) {//封装扫描的结果set.addAll(scanResult.getResult());if (!"0".equals(scanResult.getCursor())) {scanResult = jedis.scan(scanResult.getCursor(), params);} else {break;}}return set;}

如上几句代码修改,搞了一下午,特此记录,以备查看!

问题原因与思路

由于

Map<String, JedisPool> clusterNodes = jedisClusterConnection.getNativeConnection().getClusterNodes();

被修改为:

Map<String, ConnectionPool> clusterNodes = ((JedisCluster) jedisClusterConnection.getNativeConnection()).getClusterNodes();

而 ConnectionPool 类中包裹的 Connection类 没有JedisPool类中包裹的 Jedis类的 info()方法和 scan()方法;

所以我们可以有两个解题思路:

1.使用Connection中的sendCommand 模拟 info()方法和 scan()方法(只是猜想、未实现);

2.如上文中自己构建 Jedis对象;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/14016.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【SqlServer】SQL Server Management Studio (SSMS) 下载、安装、配置使用及卸载——保姆级教程

超详细的 SQL Server Management Studio (SSMS) 下载、安装、连接数据库配置及卸载教程 SQL Server Management Studio (SSMS) 是微软提供的图形化管理工具&#xff0c;主要用于连接、管理和开发 SQL Server 数据库。以下是详细的 SSMS 下载、安装、连接数据库以及卸载的完整教…

【慕伏白教程】Zerotier 连接与简单配置

文章目录 下载与安装 WindowsLinux apt安装官方脚本安装 Zerotier 配置 新建网络网络配置 终端配置 WindowsLinux 下载与安装 Windows 进入Zerotier官方下载网站&#xff0c;点击下载 在下载目录找到安装文件&#xff0c;双击打开后点击 Install 开始安装 安装完成后&…

BUU22 [护网杯 2018]easy_tornado 1

打开题目以后出现三个文件&#xff0c;查看源代码&#xff0c;突破口在于这三个文件都有特殊的格式 python的tornado漏洞 Tornado 是一个用 Python 编写的 Web 框架&#xff08;和flask一样&#xff0c;只不过flask是轻量级的&#xff0c;而tornado可以处理高流量&#xff09…

Windows Docker笔记-Docker拉取镜像

通过在前面的章节《安装docker》中&#xff0c;了解并安装成功了Docker&#xff0c;本章讲述如何使用Docker拉取镜像。 使用Docker&#xff0c;主要是想要创建并运行Docker容器&#xff0c;而容器又要根据Docker镜像来创建&#xff0c;那么首当其冲&#xff0c;必须要先有一个…

接入 deepseek 实现AI智能问诊

1. 准备工作 注册 DeepSeek 账号 前往 DeepSeek 官网 注册账号并获取 API Key。 创建 UniApp 项目 使用 HBuilderX 创建一个新的 UniApp 项目&#xff08;选择 Vue3 或 Vue2 模板&#xff09;。 安装依赖 如果需要在 UniApp 中使用 HTTP 请求&#xff0c;推荐使用 uni.requ…

攻防世界 文件上传

题目名称-文件包含 今天的题大概提一下解题思路就好了 这里要使用php://filter 在此基础上因为网页过滤了一些关键字 我们要进行爆破 UCS-4* UCS-4BE UCS-4LE* UCS-2 UCS-2BE UCS-2LE UTF-32* UTF-32BE* UTF-32LE* UTF-16* UTF-16BE* UTF-16LE* UTF-7 UTF7-IMAP UTF-8* ASCII…

胜任力冰山模型:深入探索职业能力的多维结构

目录 1、序言 2、什么是胜任力&#xff1f; 3、任职资格和胜任力的区别 4、胜任力冰山模型&#xff1a;职场能力的多维展现 4.1、冰山水面上的部分 4.2、冰山水面下的部分 4.3、深层的个人特质与价值观 5、如何平衡任职资格与胜任能力 6、结语 1、序言 在快速发展的I…

在 Flownex 中创建自定义工作液

在这篇博文中&#xff0c;我们将了解如何在 Flownex 中为流网添加和定义一种新的流体温度相关工作材料。 Flownex 物料管理界面 在 Flownex 中使用与温度相关的流体材料时&#xff0c;了解其特性与温度的关系非常重要。这种了解可确保准确预测各种热条件下的流体行为&#xff0…

工业物联网平台-视频识别视频报警新功能正式上线

前言 视频监控作为中服云工业物联网平台4.0的功能已经上线运行。已为客户服务2年有余&#xff0c;为客户提供多路视频、实时在线监视和控制能力。服务客户实时发现现场、产线、设备出现随机故障、事故等&#xff0c;及时到场处理维修。 视频识别&视频报警新功能当前正式上…

4.PPT:日月潭景点介绍【18】

目录 NO1、2、3、4​ NO5、6、7、8 ​ ​NO9、10、11、12 ​ 表居中或者水平/垂直居中单元格内容居中或者水平/垂直居中 NO1、2、3、4 新建一个空白演示文稿&#xff0c;命名为“PPT.pptx”&#xff08;“.pptx”为扩展名&#xff09;新建幻灯片 开始→版式“PPT_素材.doc…

NetCore Consul动态伸缩+Ocelot 网关 缓存 自定义缓存 + 限流、熔断、超时 等服务治理

网关 OcelotGeteway 网关 Ocelot配置文件 {//单地址多实例负载均衡Consul 实现动态伸缩"Routes": [{// 上游 》》 接受的请求//上游请求方法,可以设置特定的 HTTP 方法列表或设置空列表以允许其中任何方法"UpstreamHttpMethod": [ "Get", &quo…

数据结构与算法(test1)

一、树和二叉树 1. 看图&#xff0c;完成以下填空 (1).树的度为________。 (2).树中结点的最大层次&#xff0c;称为树的_____或树的______&#xff0c;值是______。 (3).结点A和B的度分别为________ 和 ________。 (4).结点A是结点B的________。 (5).结点B是结点A的________…

【GitLab CI/CD 实践】从 0 到 1 搭建高效自动化部署流程

网罗开发 &#xff08;小红书、快手、视频号同名&#xff09; 大家好&#xff0c;我是 展菲&#xff0c;目前在上市企业从事人工智能项目研发管理工作&#xff0c;平时热衷于分享各种编程领域的软硬技能知识以及前沿技术&#xff0c;包括iOS、前端、Harmony OS、Java、Python等…

Kubernetes是什么?为什么它是云原生的基石

从“手工时代”到“自动化工厂” 想象一下&#xff0c;你正在经营一家工厂。在传统模式下&#xff0c;每个工人&#xff08;服务器&#xff09;需要手动组装产品&#xff08;应用&#xff09;&#xff0c;效率低下且容易出错。而Kubernetes&#xff08;k8s&#xff09;就像一个…

算法与数据结构(删除有序数组的重复项)

思路 题目要求需要在原地删除重复的元素&#xff0c;这说明不能使用额外的空间。我们可以使用一个索引index来记录赋值的位置&#xff0c;以此来不断地删除重复的元素。 解题过程: 我们可以首先求得nums的长度len 若没有元素&#xff0c;直接返回0。 从第二个元素开始遍历…

[论文阅读] Knowledge Fusion of Large Language Models

Knowledge Fusion of Large Language Models (FuseLLM) Methodology 整体Pipeline如下图所示 不同的动物代表不同的LLM。左边第一&#xff0c;第二分别是Ensemble以及Weight Merging方法。最右侧为本文提出的FuseLLM。 Ensemble: 融合多个models的预测结果&#xff0c;比如…

2024~2025学年佛山市普通高中教学质量检测(一)【高三数学】

一、选择题 本题共8小题&#xff0c;每小题5分&#xff0c;共40分。在每小题给出的四个选项中。只有一项是符合题目要求的。 1、若 5 z 2 i 1 \frac{5}{z}2i1 z5​2i1&#xff0c;则 z z z A. 1-2i B. 12i C. 2-i D. 2i2、已知集合 A { x ∣ 1 < x < a } A\left\{…

探索从传统检索增强生成(RAG)到缓存增强生成(CAG)的转变

在人工智能快速发展的当下&#xff0c;大型语言模型&#xff08;LLMs&#xff09;已成为众多应用的核心技术。检索增强生成&#xff08;RAG&#xff09;&#xff08;RAG 系统从 POC 到生产应用&#xff1a;全面解析与实践指南&#xff09;和缓存增强生成&#xff08;CAG&#x…

anaconda中可以import cv2,但是notebook中cv2 module not found

一、问题 anaconda中成功import cv2 但是jupyter notebook中却无法导入cv2 二、排查 anaconda中使用python路径如下&#xff1a; jupyter notebook中使用python路径如下&#xff1a; 可以发现路径不一致。 三、解决 ①查看可用的kernel ②选中想要修改的kernel&#xff0c;打…

【数据结构】_栈的结构与实现

目录 1. 栈的相关概念与结构 2. 栈的实现 2.1 栈实现的底层结构选择 2.2 Stack.h 2.3 Stack.c 2.4 Test_Stack.c 1. 栈的相关概念与结构 1、栈&#xff1a;一种特殊的线性表&#xff0c;只允许在固定的一端插入和删除数据&#xff1b; 允许进行数据插入和删除操作的一端…