Redis Pipeline原来是这么用的

Redis(九):并发问题 上一篇介绍了 Redis 的内存管理。这节开始介绍 Redis 并发方面的问题。Redis 的单个命令是原子的,但是一个业务操作可能包含多条命令,比如以下场景:客户端查询值,并递增,在高并发场景下就可能出现并发问题,导致数据不一致。为了保证并发访问的正确性,Redis 提供了三种方法,原子操作、分布式锁、事务。本文介绍了 Redis 应对并发问题的三种方案,Redis 中的单条命令都是原子操作,而且还有 INCR/DECR 来应对简单的场景。 阅读详情

抛出,问题

最近项目碰到这么一个技术上的需求:

前端通过长轮询的机制(http long polling),获取服务端的消息数据。而服务端是需要订阅所有业务方的业务消息,再通知到给前端。

长轮询,其实简单来说,就是前端发起一个http请求,服务端把当前的请求 hang 住,直到超时或者有需要返回的内容,才return。 Apollo 配置中心就是使用这个机制实现配置的更新通知。

但有这么一种情况,假如服务端消费到消息,但此时前端与服务端的连接刚好断开了,那这个消息就没法通知到前端。

所以,我们得需要把服务端消费的消息保存下来,保证前端的每次发起长轮询的时候,都能拿到消息数据。

如果说,前端能直接订阅业务方的消息队列的话,那其实就没服务端什么关系了。当然,这是不允许的,前端不能连接咱们的消息中间件,并且业务方的消息数据也需要清洗处理后才能给到前端。

思考,方案

Apollo 的实现机制是,所有的配置都会写入数据库。每次请求过来,会去数据库获取是否有数据变更。

考虑到我们实际的业务场景,我们的业务消息其实时候时效性的,也就是说消息如果过期了,那其实也没用了。

要考虑轻量,我第一想到的就是 Redis Lists,利用其可以实现队列的特性,所以综合考虑最终采用 Redis 作为消息的存储模型。

优化,代码

Redis 的 Lists 数据结构,是简单的字符串链表,按插入顺序排序。可以在头部(Left)或者尾部(Right)添元素。

利用这个特性,我们可以实现队列(先进先出)的数据结构,搭配命令 rpush + lpop 或者 lpush + rpop 。

但是不管是 lpop 或是 rpop ,列表都只会弹出一个数据,没法达到我们的需求一次获取多个。

网上搜索了一下相关的解决方案,再结合官网的命令文档。

得出一种比较可行的方案: lrange + ltrim + pipeline

lrange 和 ltrim 是Redis Lists 的指令

lrange mylist 0 5

表示从队列头部(Left)开始取,下标为0,到下标为5的元素。如果是负数的话,表示队列尾部(Right)开始取。

ltrim mylist 0 5

ltrim 的含义是只保留指定范围的元素,上面的意思是,只保留列表下标为 0 - 5 的元素,其他的都会被删掉。

那如果要删掉前6条数据,就可能需要这么写:

ltrim mylist 5 -1

负数表示队列尾部(Right)开始取。

按实现来说, lrange + ltrim 就能实现从 List 获取多个元素的效果,为什么还需要用上 pipeline 呢?

其实这里有一个很显然的并发问题,这两个命令对于redis来说, 并不是原子操作 ,假如有其他线程在执行这两个命令的线程之间,删除了队列的一部分数据,那么第二个命令执行的时候,其实是list里面的数据已经是不对了。

而 Redis 的 pipeline 功能,可以解决我们上面说的这个问题。

大部分人可能对pipeline 比较陌生,因为平时业务上也很少用到。

先来看看 Redis Pipelining 的定义

A Request/Response server can be implemented so that it is able to process new requests even if the client hasn't already read the old responses. This way it is possible to send multiple commands to the server without waiting for the replies at all, and finally read the replies in a single step.

This is called pipelining, and is a technique widely in use for many decades. For instance many POP3 protocol implementations already support this feature, dramatically speeding up the process of downloading new emails from the server.

简单来说,它能够支持支持客户端一次发送多个命令,服务端接收到这些命令后,会统一按顺序处理,并且是在一个原子事务里。

显然,Pipelining 最明显的优势在于提高 client 与 server 的交互响应时间。将几个命令放在同一个请求中,和每个命令作为一个请求相比,效率是肯定提高的。

PS:这种方式,跟我为什么要获取多个list 数据的思路类似的。前端长轮询获取数据结果时,要返回多个数据。

话不多说,直接贴上示例代码:

@Autowired
RedisTemplate<String, Object> redisTemplate;

public void run() throws Exception {
    System.out.println("start......");
    String key = "key:list";
    Integer number = 5;
    // 每次获取5个
    List<Object> objects = redisTemplate.executePipelined(new RedisCallback<Object>() {

        @Override
        public Object doInRedis(RedisConnection connection) throws DataAccessException {
            connection.lRange(key.getBytes(StandardCharsets.UTF_8), 0, number - 1);
            connection.lTrim(key.getBytes(StandardCharsets.UTF_8), number, -1);
            return null;
        }
    });
    System.out.println(Arrays.toString(objects.toArray()));
    System.out.println("end......");
}

redisTemplate 提供了两种类型的方法:

  • executePipelined(RedisCallback action)
  • executePipelined(SessionCallback session)

这两者实现的功能都差不多,只不过 SessionCallback 比 RedisCallck 封装的更友好一下,后者的话更加底层,用法更加贴近与原生命令。

 

Redis Pipeline管道使用 1.Redis单条命令使用场景 Redis客户端连接到Redis服务端执行一条命令需要经历的步骤如下: 以上过程称为Round Trip Time(RTT,往返时间),mget和mset命令节约了RTT,但是大部分指令不支持批量操作。 Redis通过TCP来对外提供服务,Client通过Socket连接发起请求,每个请求在命令发出后会阻塞等待Redis服务器进行处理,处理完毕后将结果... 阅读详情

相关推荐

Redis Pipeline管道命令使用

概述 目录 1.Redis单条命令使用场景 2.Redis单条命令执行耗时 3.Redis连接池 4.Redis Pipeline管道命令的使用 5.总结 本文源码地址:https://github.com/online-demo/redis-pipeline.git 第1节 Redis单条命令使用场景 Redis客户端连接到Redis服务端执行一条命令需要经历的步骤如下: 上过程称为Round Trip Time(RTT,往返时间),mget和mset命令节约了RTT,但是大部分指令不支持批量操作

weixin_47367675的博客 1755

StringRedisTemplate中execute、executePipelined原理及使用

Redis事务本质:一组命令的集合 要么一起成功 要么一起失败,一个事务中的所有命令都会被序列化,在事务执行过程中会按照顺序执行注意:Redis单条命令是保证原子性的,但是事务是不保证原子性的Redis没有隔离级别的概念开启事务:multi执行事务:execRedisTemplate中如何开启并执行事务?更常见的写法仍是采用 RedisTemplate 的默认配置,即不开启事务支持。可以通过使用 SessionCallback,该接口保证其内部所有操作都是在同一个Session中。

qq_40472040的博客 5974

保姆级教程:在瑞芯微RV1126B上部署轻量化YOLOv8,实现端侧实时目标检测

本文详细介绍了在瑞芯微RV1126B芯片上部署轻量化YOLOv8模型的完整流程,包括开发环境搭建、模型训练优化、量化转换及嵌入式部署。通过利用RV1126B的3TOPS NPU算力和AI-ISP特性,实现端侧实时目标检测,提升边缘AI应用的性能和效率。

weixin_30329623的博客 267

executePipelined

pipelining(管道) Pipeline:redis的管道命令,允许client将多个请求依次发给服务器,过程中而不需要等待请求的回复,在最后再一并读取结果即可,可以改善性能. pipeline不是原子操作 pipelining实例 public void redisPop(List<String> list) { List<Object> keys = redisTemplate.executePipelined(new SessionCallback&lt

CentOS 3268

使用.NET 免费开源包ViewFaceCore做一个人脸识别并注册的功能,没有比我更全的

本文介绍了一个基于WinForm的免费人脸识别系统实现方案。系统使用AForge和ViewFaceCore库,支持从USB或电脑自带摄像头采集图像,具备人脸注册和快速识别功能。硬件方面仅需普通摄像头,软件依赖多个NuGet包(如AForge.Video、ViewFaceCore等)。界面包含视频显示、图像预览和功能按钮控件,后台采用SQLServer存储用户面部特征数据。核心代码展示了人脸检测、特征提取和多线程处理逻辑,通过ViewFaceCore实现高效识别。系统具有识别速度快、准确率高的特点,适合Win

一个靠“吃代码”长大的程序猿,专治各种“Bug 饥饿症”。 817

在Unity3d使用yolov8的onnx模型

输出OUTPUTS是float32[1,35,8400],表示它会输出一个大小为[1, 35, 8400]的浮点数张量。这个输出张量的维度表示了检测到的目标的数量、每个目标的预测参数以及网格单元的数量。输出张量的第一个维度1表示检测到的目标数量。每个目标由35个值组成,表示目标的类别、置信度、边界框的坐标及10个特定点的位置。要取得8400个数据中置信度最高的数据,然后获取该数据其他channel的数据。运行结果:(蓝色是检测手的边框,红点是自定义的点),其中的四个数字分别表示不同的维度。

shenqingyu0605202324的博客 5603

RedisTemplate使用PipeLine管道命令

一、为何用? 减少请求次数,将多条请求命令合成一次请求通过管道发给redis server,再通过回调函数一次性接收多个命令的结果,减少网络IO次数,在高并发情况下可带来明显性能提升。注意的是,redis server是单线程,多个命令合成一次请求到达redis server依然还是顺序一个个执行的,仅仅只是减少了请求IO次数。 二、如何用? RedisCallback和SessionCallBack: 1.作用: 让RedisTemplate进行回调,通过他们可以在同一条连接中一次执行多个redi

yzh_1346983557的博客 1万+

探索Vortex开源GPGPU:RISC-V SIMT架构(4-1),Execute SFU(1)

本文详细分析了Vortex RISC-V内核6级流水线中Execute阶段的SFU(特殊功能单元)模块。重点介绍了SFU的数据流结构,包含dispatch_unit、pe_switch、csr_unit、wctl_unit和gather_unit五个子模块。文章深入解析了warp控制指令wspawn和tmc的实现机制:wspawn用于激活指定数量的warp并设置新PC值,tmc则用于控制线程掩码和warp状态。通过C代码和汇编指令的对照分析,阐明了这些指令在并行计算中的关键作用,包括线程激活、状态切换和执行

weixin_55313207的博客 1363

redis之pipeline详解

一、pipeline出现的背景: redis客户端执行一条命令分4个过程: 发送命令-〉命令排队-〉命令执行-〉返回结果 1 这个过程称为Round trip time(简称RTT, 往返时间),mget mset有效节约了RTT,但大部分命令(如hgetall,并没有mhgetall)不支持批量操作,需要消耗N次RTT ,这个时候需要pipeline来解决这个问题 二、pepeline的...

疯一样的女子 1万+

linux 内核vxlan收发包流程

1.vxlan口收包处理流程 前面几章详细介绍了vxlan接口的使用,而且已经知道vxlan是 MAC IN UDP中的封装,因此,在解封装之前,一切按照原有流程走,在此复习一下内核收发包流程(驱动层的数据处理这次不再解析,直接从__netif_receive_skb_core开始) #物理网卡处理中断,触发softirq i40e_intr └─napi_schedule_irqoff #i40e softirq把包放到per cpu backlog,触发softirq i40e_napi_p

魏言华的博客 3826

内容创作全流程自动化:OpenClaw+大模型搞定选题+写稿+多平台发布

本文介绍了一套基于OpenClaw的全自动化内容创作流水线方案,帮助垂直领域创作者摆脱重复劳动。该方案将内容生产拆解为选题生成、内容撰写、格式适配、多平台发布四个模块,通过工作流引擎串联执行。系统能自动采集热榜生成选题、调用大模型撰写结构化内容、适配不同平台格式要求,并通过API+浏览器自动化实现多平台发布,全程只需人工最终审核。作者分享了各模块的实现细节,包括热榜采集、内容结构化生成、Markdown转换和发布策略,并提供了工作流编排方法。这套方案能为创作者每天节省约3小时,同时保证内容质量和发布效率。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 49

Redis Pipeline讲解

一、pipeline出现的背景 Redis是一种基于客户端-服务端(CS)模型以及请求/响应协议的TCP服务,这意味着通常情况下一个请求会遵循以下步骤: 客户端向服务端发送一个查询请求,并监听Socket返回,通常是以阻塞模式,等待服务端响应。 服务端处理命令,并将结果返回给客户端。 这样一次命令消耗的时间就包括四个部分:请求从客户端到服务器的时间、命令排队的时间和命令真正执行时间、结果从服...

diweikang的博客 2893

机器学习势能(MLPs) 第一章 基础理论与核心概念 第二章 数据生成与训练集构建

密度泛函理论(DFT)作为现代计算材料科学的基石,通过求解Kohn-Sham方程在电子结构层面提供可靠的势能面信息。然而,其计算复杂度随体系电子数呈O(N3) 至O(N4) 增长,对于包含数百个原子的体系,单点计算往往需消耗数小时至数天的计算资源。这一瓶颈严重限制了分子动力学模拟的时间尺度,传统DFT-MD通常仅能覆盖皮秒量级,远不足以观测扩散、相变等慢动力学过程。经验力场通过解析函数形式描述原子间相互作用,实现了经典力学的计算效率,但其参数化过程高度依赖物理直觉与经验调参。

VectorShift的博客 182

Redis之pipeline与事务

Redis使用的是网络模型,也就是io多路复用+非阻塞io的异步处理流程(注册事件,在事件循环callback处理事件)。我们可以将每个连接抽象看成一个pipe,哪个pipe中的数据先满就先处理。注意,单reactor指的是acceptor只有一个,而工作线程在6.0版本之前只有一个,也就是单reactor单线程,6.0版本之后就是单reactor多线程。下图为6.0版本之后的reactor模型。但之后的讨论我们基于6.0版本之前,也就是单reactor单线程。

oxygen3000的博客 1601

淘宝母婴用品数据挖掘及可视化分析研究

1. 背景介绍 在当今的电子商务时代,母婴用品市场已经成为了各大电商平台的一片蓝海。淘宝作为中国最大的电子商务平台,其上的母婴用品交易数据自然引人关注。理解这些数据,可以帮助商家更好地制定营销策略,也可以帮助消费者更好地选择产品。因此,本文将对淘宝母婴用品的数据进行深入的挖掘和分析。 1.1 电子商务的

AI天才研究院 1258

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Redis Pipeline技术

Redis Pipeline通过批量执行命令减少网络往返次数,提高性能和吞吐量。它降低了延迟,简化了客户端代码,同时保证了操作的原子性。使用Jedis库,可以轻松在Java中实现Redis Pipeline。示例代码展示了如何连接到Redis服务,获取Pipeline实例,添加命令,执行并处理结果。在生产环境中,需优化Jedis配置以提高性能和可靠性。

技术铺掌柜 1416

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

如何用好redis pipeline

戳蓝字「TopCoder」关注我们哦!编者注:pipeline是Redis的一个提高吞吐量的机制,适用于多key读写场景,比如同时读取多个key的value,或者更新多个...

luoxn28的专栏 594

VB摄像头监控

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

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

redis:Redis Pipeline深度解析

Redis Pipeline(管道)是一种批量执行命令的优化机制,其核心价值在于。传统模式下,客户端执行一条命令需要经历"发送请求-等待响应"的往返过程,而Pipeline允许客户端一次性发送多条命令,服务器批量处理后一次性返回结果,从而显著降低网络延迟带来的性能损耗。

weixin_43290370的博客 1270

Redis的Pipeline

Redis Pipeline机制通过批量发送命令优化网络性能,减少往返通信次数。相比传统单命令模式,Pipeline允许客户端一次性发送多个指令,服务器顺序执行后返回结果。该机制与事务不同,不保证原子性。通过Java Jedis客户端示例展示了Pipeline的典型用法:批量执行set、append、incr等操作后统一获取响应,显著提升批量处理效率,特别适合高延迟网络环境下的Redis操作优化。

weixin_41510616的博客 821

Redis pipeline

Redis pipeline

1020

Redis 使用 Pipeline 加速查询速度

如果使用的是本地环回接口,RTT 就短得多,但如如果需要连续执行多次写入,这也是一笔很大的开销。Redis 很早就支持 Pipeline 技术,因此无论你运行的是什么版本,你都可以使用 Pipeline 操作 Redis。使用 Pipeline 发送命令时,每次 Pipeline 组装的命令个数不能没有节制,否则一次组装的命令数据量过大,一方面会增加客户端的等待时间,另一方面会造成一定的网络阻塞,可以将一次包含大量命令的 Pipeline 拆分成多个较小的 Pipeline 来完成。

SmartSi 1303

php redis 如何使用pipeline,redis中pipeline详解

一、pipeline出现的背景:redis执行一条命令有四个过程:发送命令、命令排队、命令执行、返回结果;这个过程称为Round trip time(简称RTT, 往返时间),mget mset有效节约了RTT,但大部分命令(如hgetall,并没有mhgetall)不支持批量操作,需要消耗N次RTT ,这个时候需要pipeline来解决这个问题。二、pepeline的性能1、未使用pipelin...

weixin_39606118的博客 1330

Redis之PipeLine

文章目录背景性能对比适用场景注意事项 背景 Redis是使用请求/响应协议的TCP服务器,所以说通常的执行流程如下: 客户端发送请求,同时监听对应的socket,等待服务端响应,一般是一个阻塞的状态 服务端将结果发送给客户端,客户端获取到结果 整个流程如图: 由官方提供的数据来看,Redis每秒可以进行100000+次查询,但是这只是查询的性能,在实际操作中,还需要进行TCP报文的打包和发送...

SCUTJAY的博客 499

Redis批处理之pipeline

前言 Redis是基于TCP连接进行通信 Redis是使用客户端 - 服务器模型的TCP服务器,称为请求/响应协议。 这意味着通常一个请求是通过以下步骤完成的: 客户端向服务器发送查询,并通常以阻塞的方式从套接字读取服务器响应。 服务器处理命令并将响应发送回客户端。 知道redis是基于TCP连接进行通信的,每一个request/response都需要经历一个RTT(Round-Trip Ti...

ChengYanan的博客 813
上一篇: 真的是最全的一致性hash环讲解了
下一篇: 那些年我们一起优化的SQL
Javaesandyou
博客等级 码龄5年 742粉丝 563原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值