redis-cluster主流客户端驱动不支持pipeline,该怎么解决。

redis集群客户端JedisCluster优化 - 管道(pipeline)模式支持 redis集群客户端JedisCluster优化 - 管道(pipeline)模式支持Redis在3.0版正式引入了集群这个特性,扩展变得非常简单。然而当你开心的升级到3.0后,却发现有些很好用的功能现在工作不了了, 比如我们今天要聊的pipeline功能。 我们知道,普通的情况下,redis client与server之间采用的是请求应答的模式,即: Client: command1 阅读详情

redis-cluster,是基于redis的基础上开发分布式缓存数据库系统。

1、redis-cluster集群的特点:

1)无中心节点(share-nothing)架构,各个节点对等,每个节点存储集群数据的一部分。

2)集群数据分布在所有master节点上的16384个slots中,无冗余。

3)通过redis配置slave节点,完成数据备份存储以及提供failover节点。

4)redis cluster提供HA方案。节点之间通过gossip协议进行通信,交换节点的状态信息;如果超过半数以上的master节点与故障节点通信超时,则认为该节点是故障节点,则通过投票协议完成选举,实现redis 主从节点自动切换(auto-failover)。

5)直接ASK 转向/MOVED 转向机制.

6)redis cluster支持在线扩容、迁移和升级。

2、redis-cluster不足之处:

1)任意master挂掉,且当前master没有slave时,集群进入fail状态;

2)如果集群中超过半数的master故障,不管故障master是否有存活的salve,集群都会进入fail状态;

3)目前主流的redis-cluster客户端均不支持pipeline操作(这节所讲的重点)

3、如何实现redis-cluster的pipeline操作?

redis是一个cs模式的tcp-server,使用和http类似的请求响应协议,一个client可以通过一个socket链接发送多个请求命令。每次client发出请求命令后通常会阻塞等待server处理请求,server端处理完请求命令后给客户端返回响应报文。如果我们发送四次请求,需要8个tcp报文才能完成,其中如果包含报文发送时间,网络延时,这极大的浪费了redis server的处理数据的能力。具体通信过程如下:

client: set f1 1

server:OK

client: set f2 1

server:OK

client: set f3 1

server:OK

client: set f4 1

server:OK

如果我们利用redis的pipeline操作,我们则可以把多个命令打包成一个请求报文一次性发送给redis服务端,这样就不需要等待单条命令执行结果的返回,而redis服务端会处理完多条命令后会将多条命令的处理结果打包到一起返回给客户端。通信过程如下

client: set f1 1

client: set f2 1

client: set f3 1

client: set f4 1

server:OK

server:OK

server:OK

server:OK

但是目前redis-cluster客户端并不支持pipeline操作,客户端在初始化redis集群数据的时候,使用的是JedisCluster而不是Jedis对象,而JedisCluster 并没有发现提供有像Jedis一样的获取Pipeline对象的 pipelined()方法.

    private static JedisCluster jc;
    
    private final static String REDIS_CLUSTER_HOSTS = "redis_cluster_hosts";
    
    static {
        String redis_cluster_hosts = Config.getConfigValue(REDIS_CLUSTER_HOSTS);
        String[] redis_hosts = redis_cluster_hosts.split(",");
        Set<HostAndPort> jedisClusterNodes = new HashSet<HostAndPort>();
        for(String redisNode:redis_hosts){
            String[] hostPort = redisNode.split(":");
            HostAndPort hostAndPort = new HostAndPort(hostPort[0], Integer.parseInt(hostPort[1]));
            jedisClusterNodes.add(hostAndPort);
        }
        jc = new JedisCluster(jedisClusterNodes);
    }

根据redis-cluster的特性,集群数据分布在所有master节点上的16384个slots中,redis客户端在存储key的时候,首先是计算key存储的slot,再通过集群中solt与节点的映射,插入到对应的slot的master节点中。

如果我们需要支持批量操作,第一步,我们需要通过下面代码得到slotHostMap映射:

Map<String, JedisPool> nodeMap = jc.getClusterNodes();
String anyHostAndPortStr = nodeMap.keySet().iterator().next();
TreeMap<Long, String> slotHostMap = getSlotHostMap(anyHostAndPortStr);
/**
 * 获取slot与host对应关系
 * @param anyHostAndPortStr
 * @return
 */
private static TreeMap<Long, String> getSlotHostMap(String anyHostAndPortStr) {
    TreeMap<Long, String> tree = new TreeMap<Long, String>();
    String parts[] = anyHostAndPortStr.split(":");
    HostAndPort anyHostAndPort = new HostAndPort(parts[0], Integer.parseInt(parts[1]));
    Jedis jedis = null;
    try{
        jedis = new Jedis(anyHostAndPort.getHost(), anyHostAndPort.getPort());
        List<Object> list = jedis.clusterSlots();
        for (Object object : list) {
            List<Object> list1 = (List<Object>) object;
            List<Object> master = (List<Object>) list1.get(2);
            String hostAndPort = new String((byte[]) master.get(0)) + ":" + master.get(1);
            tree.put((Long) list1.get(0), hostAndPort);
            tree.put((Long) list1.get(1), hostAndPort);
        }
    }catch(Exception e){
        logger.error("getSlotHostMap error",e);
    }
    return tree;
}

通过上面的代码,我们可以得到每个master节点上分布的slot。这样我们就可以通过key计算出slot,再通过slot找到对应存储的节点。

  int slot = JedisClusterCRC16.getSlot(key); 
        //获取到对应的Jedis对象
        Map.Entry<Long, String> entry = slotHostMap.lowerEntry(Long.valueOf(slot));
        Jedis jedis = nodeMap.get(entry.getValue()).getResource();

找到了Jedis对象,那我们就可以通过jedis.pipelined()创建pipeline对象实现pipeline了。

在我们暴露给其他开发人员使用的批量操作方法中,是支持多个key批量操作,在计算每个key存储的slot之后,我们需要对通过节点上的key进行分类,然后分批通过pipeline操作同一个redis节点。

 public static String batchSet(Map<String,String> keyValues){
        logger.error("keymap size={}",keyValues.size());
        //通过key获取到相应的node,再通过node把key做分类
        Map<String, Map<String, String>> todoMap = getNodeKeyMap(keyValues);
        try {
            //todoMap保存了node与key之间的一对多的映射关系
            for(String key:todoMap.keySet()){
                Jedis jedis = nodeMap.get(key).getResource();
                Map<String, String> kv = todoMap.get(key);
                if(kv.size() > 0){
                    Pipeline p = jedis.pipelined();
                    for(String _key:kv.keySet()){
                        p.set(_key, kv.get(_key));
                    }
                    p.sync();
                }
            }
        } catch (Exception e) {
          logger.error("batchSet error",e);
        }
        return null;
    }

以上的一系列操作,最终的目的还是为了获取到单个master节点的Jedis对象,获取到pipeline对象。

休息之余总结出来的方法,如果大家有更好的方法,欢迎一起探讨。qq:1549690699


数据库之Redis运维手册(私人整理) 1、redis配置文件 #cat 8000.conf daemonize no #[yes/no]默认值no,该参数用于定制redis服务是否以守护模式运行。 pidfile /var/run/redis.pid #默认值/var/run/redis.pid,指定redis服务的进程号文件路径,以守护模式运行时需要配置本参数; port 8000 #默认值6379,指定redis服务... 阅读详情

相关推荐

Redis 八股文深度解析:线程模型、内存管理与事务机制全掌握

在后端开发与系统设计中,高性能缓存是解决高并发读写压力的关键技术,而 Redis 作为内存数据结构的代表,其底层原理常成为面试与性能调优的焦点。理解 Redis 的快速响应机制,不能仅停留在“基于内存”的表面,更需深入其单线程执行模型、IO 多路复用、高效数据结构编码以及内存淘汰策略等核心设计。例如,LRU 与 LFU 等淘汰算法如何影响缓存命中率,MULTI/EXEC 事务为何与关系型数据库的 ACID 特性存在差异。掌握这些原理,不仅能应用于缓存穿透、击穿、雪崩等经典场景的治理,还能指导 bigkey

weixin_30899023的博客 288

Redis cluster使用pipeline

本场 Chat 分享主要介绍如何在Redis cluster模式下使用jedis的pipeline方法。 本场 Chat 内容将涉及如下: Redis cluster模式下使用jedis的常见方法; Redis cluster模式下使用jedis的pipeline方法; ...

GitChat 1194

机器学习解决方案架构:从GCP落地到生产稳定的实战地图

机器学习解决方案架构(ML Solution Architecture)是保障AI项目从实验走向高可用生产的核心工程范式,其本质是通过分层设计、可观测性建设与成本敏感型决策,在数据接入、特征工程、模型服务和应用集成四大环节建立故障隔离边界与可验证交付标准。它超越单一算法选型,聚焦数据Schema治理、特征一致性保障、在线服务熔断机制及API网关业务规则注入等关键实践,直接支撑金融风控、电商推荐、工业质检等真实场景的10万QPS稳定推理与分钟级故障定位。本文基于GCP/Vertex AI技术栈,系统拆解可落地

culuo8053的博客 628

--Redis入坑--RedisPipelineException:Pipeline contained one or more invalid commands;WRONGTYPE ...

异常说明 最近在写代码的时候,redis报了如下错误: org.springframework.data.redis.connection.RedisPipelineException: Pipeline contained one or more invalid commands; nested exception is io.lettuce.core.RedisCommandException: WRONGTYPE Operation against a key holding the wrong k

qq_41120902的博客 9898

NoSQL选型本质:从业务读写模式匹配数据模型

NoSQL并非关系型数据库的简单替代,而是基于文档、宽列、键值、搜索四种核心数据模型,对现实业务约束进行结构性解耦的技术范式。其底层原理在于存储结构与查询路径的强绑定——MongoDB的BSON序列化决定IO效率,Cassandra的分区键定义物理磁盘布局,Redis的数据结构即API契约,Elasticsearch的倒排索引重构检索逻辑。这种模型驱动的设计,使NoSQL在高并发、海量时序、亚秒级搜索等场景具备不可替代的技术价值。典型应用场景包括实时风控(Redis)、设备监控(Cassandra)、内容管

weixin_30600197的博客 440

Redis

redis

の博客 381

为什么RedisCluster无法使用pipeline

我们知道,Redis 集群的键空间被分割为 16384 个槽(slot),集群的最大节点数量也是 16384 个。每个主节点都负责处理 16384 个哈希槽的其中一部分。具体的redis命令,会根据key计算出一个槽位(slot),然后根据槽位去特定的节点redis上执行操作。如下所示: master1(slave1): 0~5460 master2(slave2):5461~10922 master3(slave3):10923~16383 集群有三个master节点组成,其中master1分配了

搓搓那年时光静好 2990

Matlab TreeBagger实战:用随机森林预测房价的5个关键步骤(附完整代码)

本文详细介绍了使用Matlab的TreeBagger工具包构建随机森林模型预测房价的完整流程。通过波士顿房价数据集实战,涵盖数据预处理、模型构建、参数调优、特征重要性分析及高级应用(如分位数回归)等5个关键步骤,并附有完整代码,帮助读者快速掌握这一强大的回归分析工具。

ol789012的博客 444

关于在Redis集群模式下不支持Scan和pipline的解释以及解决方案

 最近在写程序的过程中遇到一个问题,就是需要删除redis中key值以某个字符串开头的数据。因为通过查阅资料以后说如果数据量过大使用keys可能会产生死锁,并且速度会很慢,所以通过查阅各种资料发现使用scan会是比较好的一种方案,但是在真实的开发过程中发现了单节点的redis会支持scan但是集群环境中并不支持scan命令(本人使用的是redistemplate),不仅如此并且之前所熟知的Pipl...

TankyZhang的博客 1万+

Android Framework之Pkms详解

system 用户并没有访问应用程序目录的权限,但是 Installd 服务是以 root 用户启动的,可以访问 /data/data/ 下的目录,Installd 需要完成一些创建应用数据的任务。Installer 服务是 Android 提供的用于安装的服务,Installer 持有 Installd 守护进程对应的 Binder 服务的代理对象,本质上是通过 Binder 通信调用底层的 Installd 服务真正完成 APK 文件格式的优化和转换、建立相关的数据目录、删除文件、安装应用等工作。

门徒07的博客 1842

YOLOv5源码逐行超详细注释与解读(1)——项目目录结构解析

全网最全YOLOv5项目目录结构超详细分析。逐个文件注释,小白上手必备

路人贾的博客 9万+

Redis 知识体系(文档型 NoSQL)

本文深入解析Redis八大基础数据结构及其底层编码实现,涵盖String、List、Set、ZSet、Hash、Geo、Bitmap、HyperLogLog和Stream等核心结构。通过源码级分析,揭示了SDS、Ziplist、Dict等底层组件的设计原理,并详细探讨了Redis的高性能IO模型、持久化机制(RDB/AOF/混合模式)、内存管理策略及高可用架构(主从/哨兵/Cluster)。 重点剖析了Redis在工程实践中的典型问题与优化方案,包括缓存穿透/击穿/雪崩的解决方案、分布式锁的完整实现(含Re

专注 Java 后端开发,分享基础语法、JVM、并发、Spring 全家桶、微服务、分布式、性能优化等实战干货。坚持输出高质量技术笔记,用简单语言讲清复杂原理,助力每一位 Java 开发者稳步进阶。 796

【华为OD机试真题】6、数组去重和排序 | 机试真题+思路参考+代码解析(C++、Java、Py、C语言、JS)

题目描述 >给定一个乱序的数组,删除所有的重复元素,使得每个元素只出现一次,并且按照出现的次数从高到低进行排序,相同出现次数按照第一次出现顺序进行先后排序

KJ.JK 3889

爬虫教程( 4 ) --- scrapy-redis、集群、curl-cffi、scrapy-stealth、aio-scrapy、omnicrawl-core、反检测(反爬)浏览器

分布式爬虫 scrapy-redis、集群

freeking101的博客 6826

AI辅助Android开发:从传统到智能化的技术演进

AI辅助开发的核心在于利用算法模型自动化或优化传统任务。在Android开发中,AI可应用于需求分析、设计、编码、测试和维护各阶段。需求分析:AI工具如基于NLP的模型(例如GPT系列)可解析用户需求文档,自动生成用户故事和原型设计。假设产品需求为“开发一个航班查询应用”,AI能提取关键词,输出UML图或伪代码。代码生成:使用AI代码助手(如GitHub Copilot),工程师输入自然语言描述,AI生成Java/Kotlin代码片段。

郑伟强dev的专栏 137

用ChatGPT 5.5掌握SCI的4个实操润色技巧,论文质量极速提升!(附提示词)

ChatGPT 5.5的发布,在学术写作中的应用变得更加精准和安全,通过正确的使用方法,不仅可以改善语法与表达,让论文达到SCI发表水准,还能最大程度保留作者原意,将AIGC检测率控制在低风险区间。可以帮大家省下大量纠结语法、梳理逻辑的时间,在保证润色质量的同时,兼顾AIGC检测的合规要求,为论文投稿成功率提供实实在在的提升。通过智能调整语序、优化用词和句式结构,该方法能够在保留学术质感的同时,使文章表达更自然、贴近人工撰写的风格,从而避免文字过于程式化,提升论文整体可读性和表达的个性化特征。

智能AI让学术科研更容易 64

【Redis】原理篇 3w字详解

try {// 1.建立连接// 2.获取输出流、输入流// 3.发出请求// 3.1.获取授权 auth 123321// 3.2.set name 虎哥sendRequest("set", "name", "虎哥");// 4.解析响应// 3.2.set name 虎哥// 4.解析响应// 3.2.set name 虎哥// 4.解析响应// 5.释放连接try {if (reader!if (writer!

ashiho的博客 560

爆破shadow文件密码脚本(完成版)

由于添加了一个for循环,再稍作修改,让password not found!print(f"Trying password:")显示爆破的密码和过程。将代码中的password="123456"替换成下面代码。line.strip()函数首尾去空格。

m0_56578216的博客 772

召回系统数据准备:YAML配置驱动与Pydantic验证实践

在推荐与搜索系统中,召回环节负责从海量候选集中快速筛选相关物品,其性能直接影响用户体验。为实现高效召回,业界普遍采用数据预处理与分层存储架构,将业务数据离线加工成向量、画像等专用格式,以解耦在线服务、优化查询性能。这一过程的核心是配置驱动的数据流水线,它通过定义数据源、转换规则与输出目标,实现流程的灵活编排与敏捷迭代。本文聚焦于使用YAML进行复杂配置管理,并结合Pydantic实现强类型验证与安全渲染,确保数据生成任务的稳定与可维护性,为向量召回、实时画像等场景提供可靠的数据供给。

weixin_34184158的博客 326

从 SAP HANA 到 ABAP Cloud:彻底讲透 scalar function 的定位、实现方式与 Clean Core 实践

SAP项目中,scalar function是数据库层的重要计算单元,用于封装可复用的单值逻辑。不同于返回结果集的table function,它直接嵌入SQL表达式,适用于折扣率计算、数据标准化等场景。在SAP技术栈中,scalar function有三种形态:原生SQLScript函数、AMDP托管函数和CDS绑定函数。正确使用可提升查询性能,但需注意与procedure、table function的边界区分。AMDP scalar function是ABAP项目中的推荐实现方式,能确保函数生命周期受

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1678

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

【人工智能专题】Redis 杀进 AI 数据层:向量搜索、语义缓存与 Agent 记忆工程从入门到踩坑

大多数团队手里已经有一个 Redis 在跑缓存。这篇文章要回答的是:能不能、该不该把它升级成 AI 应用的向量库 + 语义缓存 + Agent 记忆层。全文围绕 Redis 8.0 到 8.6 的 AI 能力演进展开,包含 Query Engine 与 Vector Sets 两条向量检索路径的完整对比、FT.HYBRID 混合检索、语义缓存的三种落地方式(RedisVL / Vector Sets 手写 / LangCache 托管)、语义路由、以及 Agent 记忆的双层模型。

weixin_42260382的博客 489

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

【Canal】实现原理和搭建方案

canal.adapter,相当于canal的客户端,会从canal-deployer中获取数据,然后对数据进行同步,可以同步到MySQL、Elasticsearch和HBase等存储中去。(1)全局配置:conf/application.properties(也可以是conf/application.yml,连接 Canal-Server、配置同步目标、全局参数)下载canal.deployer,可以直接监听MySQL的binlog,把自己伪装成MySQL的从库,只负责接收数据,并不做处理。

weixin_44823875的博客 944

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Java最高频八股文速通

final 类:String 类被声明为 final,这意味着它不能被继承,从而防止了通过继承改变其行为。final 字段:String 类中的 value 字段是 final 的,这保证了 String 对象在创建后其内部字符数组不会被改变。没有提供修改方法:String 类没有提供任何可以修改其内容的方法。所有对 String 的操作(如拼接、替换等)都会生成一个新的String 对象。

qq_43751506的博客 6395

AI编程代理如何深度集成CI/CD与测试流程

AI编程代理已从代码补全工具演进为可嵌入真实软件工程流水线的智能执行单元。其核心原理在于打破沙盒隔离,通过环境镜像同步、事件驱动触发和双向状态回写,实现与Jira、GitLab、SonarQube等企业级工具链的语义级集成。技术价值体现在显著降低CI失败率(63%→4.2%)、提升测试有效性(+41%)及增强发布可审计性。典型应用场景包括自动化单元测试生成、Pipeline根因诊断、SBOM可信链构建与Changelog合规生成。本文聚焦Devin在金融级CI/CD、Testing与Integrations

技术百科 604

并行分布式框架:Celery、rq、funboost

Celery是一个异步任务的调度工具,也可以叫做 "分布式任务队列(Distributed Task Queue)"。

freeking101的博客 5万+

Node.js与WebSocket实现实时通信全攻略

WebSocket协议作为HTTP协议的补充,实现了真正的全双工通信,解决了传统HTTP轮询的效率问题。其核心原理是在单个TCP连接上建立持久化通道,允许服务端主动推送数据,特别适合实时性要求高的场景。Node.js凭借事件驱动和非阻塞I/O特性,成为构建WebSocket服务的理想平台。在电商大促、在线协作、金融交易等场景中,这种技术组合能轻松应对每秒上万级的并发请求。通过心跳检测、二进制传输、Redis广播等进阶技巧,开发者可以构建高性能的实时通信系统。本文以电商订单状态更新为案例,详细讲解从环境搭建到

weixin_34221276的博客 395
上一篇: 使用filter解决xss攻击
下一篇: 发生死锁的线程dump日志
南方的北方
博客等级 码龄14年 7粉丝 35原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值