【实践篇】redis管道pipeline使用详解

news2024/11/25 16:47:08

文章目录

  • 0. 前言
    • 什么场景下使用redis管道特性
  • 1.原理
    • 1.1 redis管道特性的处理机制
  • 使用redis管道优化示例
  • 3. springboot使用redis管道示例
  • 4. 参考资料
  • 5. 源码地址
  • 6. Redis从入门到精通系列文章

在这里插入图片描述

0. 前言

Redis管道(Pipeline)是一种批量执行Redis命令的机制。通常情况下,客户端向Redis发送一个命令时,需要等待Redis服务器执行完该命令并返回结果后才能发送下一个命令。但使用管道可以在客户端一次性发送多个命令,然后等待Redis服务器一次性返回所有命令的结果,从而减少了多次网络往返的开销。

在管道中,客户端发送的每个命令都会被Redis服务器缓存起来,而不是立即执行。当客户端调用执行命令的方法(如EXEC)时,Redis服务器会按照命令发送的顺序依次执行这些命令,并将执行结果一次性返回给客户端。这样就实现了一次性发送多个命令并一次性接收多个结果的效果。

通过使用管道,可以大大提高Redis的性能和吞吐量。因为管道允许客户端一次性发送多个命令,减少了网络延迟和连接开销。此外,管道还支持原子性的事务操作,可以将多个命令封装在一个事务中进行执行。

由于管道是无序的,所以返回结果的顺序可能与命令的发送顺序不一致。在使用管道时,客户端需要根据实际情况进行结果的解析和处理。

什么场景下使用redis管道特性

Redis管道特性在以下场景下可以发挥作用:

  1. 批量操作:当需要执行大量Redis操作时,使用管道可以将多个操作合并到一次网络往返中,减少了网络延迟和连接开销,大大提高了性能。例如批量写入、批量读取、批量删除等。

  2. 高吞吐量:管道可以并行地执行多个Redis操作,提高了系统的并发处理能力,从而实现高吞吐量的数据处理。

  3. 数据流水线:当需要依次执行多个Redis命令,并且后续命令的执行依赖于前面命令的结果时,可以使用管道来实现数据的流水线处理。例如计算、过滤、排序等操作可以通过管道一次性完成。

  4. 批量查询:当需要查询多个键对应的值时,使用管道可以将多次查询合并为一次查询,减少了多次网络往返的开销,提高了查询效率。

  5. 事务操作:在Redis中,事务是通过MULTI/EXEC命令实现的,使用管道可以将多个命令一起发送给Redis服务器,实现原子性的事务操作。这样可以减少网络往返的次数,提高事务的执行效率。

Redis管道特性适用于需要高性能、高并发、批量操作的场景,可以有效地提升Redis的操作效率和系统的整体性能。但管道操作是无序的,返回结果的顺序可能与命令的发送顺序不一致,因此在使用管道时需要根据实际情况进行结果的解析和处理。

1.原理

Redis管道可以与TCP连接复用一起使用。在使用管道时,可以选择在同一个TCP连接上发送多个命令,而无需每次都建立和关闭连接。这样可以减少连接的开销,提高数据传输的效率。

从TCP连接的角度来解释Redis管道提升性能原理,主要涉及到以下几个方面:

  1. 建立TCP连接:在客户端与Redis服务器建立连接时,会通过TCP三次握手来建立可靠的连接。客户端与服务器之间的通信会通过该TCP连接进行。

  2. 消息传输:在Redis管道中,客户端发送的多个命令请求会被缓存到请求队列中,而不是立即发送到Redis服务器。这些请求会在客户端本地进行缓存。

  3. 批量发送:当客户端调用执行命令的方法(如EXEC)时,客户端会将请求队列中的命令一次性发送到Redis服务器。这样就减少了网络往返的次数,提高了性能。客户端通过TCP连接将命令一批一批地发送给服务器。

  4. 执行命令:Redis服务器收到客户端发送的命令后,会按照请求队列中的命令顺序依次执行这些命令。执行完所有命令后,将执行结果一次性返回给客户端。

  5. 关闭连接:当管道中的所有命令执行完毕后,客户端可以选择关闭TCP连接或者继续发送其他命令。如果不关闭连接,客户端可以在后续的操作中继续使用该TCP连接进行通信。

Redis管道的原理基于TCP连接的建立和消息传输机制。通过在客户端本地缓存多个命令请求,然后一次性发送到Redis服务器,减少网络往返的开销,提高性能。同时,通过TCP连接的保持,可以在不关闭连接的情况下继续使用管道进行后续的操作。

1.1 redis管道特性的处理机制

Redis的管道实现原理主要依靠以下两个机制:

  1. 请求队列:客户端发送的命令请求会先进入一个请求队列,而不是立即发送到Redis服务器。请求队列会按照命令的发送顺序缓存请求,保持命令的顺序不变。

  2. 批量执行:当客户端调用执行命令的方法(如EXEC)时,Redis服务器会按照请求队列中的命令顺序依次执行这些命令,并将执行结果一次性返回给客户端。这样就实现了一次性发送多个命令并一次性接收多个结果的效果。

具体的实现流程如下:

  1. 客户端发送命令:客户端将多个命令发送到Redis服务器。这些命令会被添加到请求队列中。

  2. REDIS_PIPELINE 指令:客户端发送一个特殊的REDIS_PIPELINE指令给Redis服务器,表示开始使用管道。

  3. 请求队列缓存命令:Redis服务器收到REDIS_PIPELINE指令后,将客户端发送的命令添加到请求队列中。

  4. 执行命令并返回结果:当客户端调用执行命令的方法(如EXEC)时,Redis服务器会按照请求队列中的命令顺序依次执行这些命令。执行完所有命令后,将执行结果一次性返回给客户端。

通过使用请求队列和批量执行机制,Redis的管道实现了一次性发送多个命令并一次性接收多个结果的效果,从而减少了多次网络往返的开销,提高了性能和吞吐量。同时,管道还支持原子性的事务操作,可以将多个命令封装在一个事务中进行执行。

使用redis管道优化示例

通常在项目中发现大量使用循环操作redis的示例。使用循环单独更新缓存这种在大数据量情况下存在很大性能问题。

举个简单示例

假设有一个需求是根据用户ID列表批量更新用户的缓存信息。原始的实现方式是使用循环单独更新每个用户的缓存信息,如下所示:

import redis.clients.jedis.Jedis;

public class CacheUpdater {
    private Jedis jedis;

    public CacheUpdater() {
        jedis = new Jedis("localhost", 6379);
    }

    public void updateCache(List<String> userIds) {
        for (String userId : userIds) {
            User user = getUserFromDB(userId); // 从数据库获取用户信息
            updateCache(user); // 更新缓存信息
        }
    }

    private void updateCache(User user) {
        String cacheKey = "user:" + user.getId();
        jedis.set(cacheKey, user.toJson());
    }

    private User getUserFromDB(String userId) {
        // 从数据库中获取用户信息的逻辑
    }
}

上面代码中,每次循环都会单独更新一个用户的缓存信息,导致每次都要进行网络通信,性能较差。

使用Redis管道优化后的代码如下所示:

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;

public class CacheUpdater {
    private Jedis jedis;

    public CacheUpdater() {
        jedis = new Jedis("localhost", 6379);
    }

    public void updateCache(List<String> userIds) {
        Pipeline pipeline = jedis.pipelined();
        for (String userId : userIds) {
            User user = getUserFromDB(userId); // 从数据库获取用户信息
            updateCache(user, pipeline); // 更新缓存信息
        }
        pipeline.syncAndReturnAll();
    }

    private void updateCache(User user, Pipeline pipeline) {
        String cacheKey = "user:" + user.getId();
        pipeline.set(cacheKey, user.toJson());
    }

    private User getUserFromDB(String userId) {
        // 从数据库中获取用户信息的逻辑
    }
}

在优化后的代码中,创建了一个Redis管道Pipeline对象pipeline,然后在循环中使用管道的set命令批量更新缓存信息。最后,通过pipeline.syncAndReturnAll()一次性执行所有的管道命令。

通过使用Redis管道优化,可以减少网络通信的开销,提高性能。

3. springboot使用redis管道示例

在Spring Boot中使用Redis管道,可以借助RedisTemplate和SessionCallback来实现。

  1. 如何使用Redis管道进行批量查询车辆最新位置GPS信息。
    注入RedisTemplate在getLatestGpsInfo方法中使用executePipelined方法来执行Redis管道操作。在管道中,遍历车辆ID列表,使用RedisConnection对象的get方法来获取对应车辆的GPS信息。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class VehicleService {
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    public List<GpsInfo> getLatestGpsInfo(List<String> vehicleIds) {
        List<GpsInfo> gpsInfoList = redisTemplate.executePipelined(new RedisCallback<List<GpsInfo>>() {
            @Override
            public List<GpsInfo> doInRedis(RedisConnection connection) {
                for (String vehicleId : vehicleIds) {
                    connection.get(redisTemplate.getStringSerializer().serialize("gps:" + vehicleId));
                }
                return null;
            }
        });

        // 解析返回结果
        List<GpsInfo> result = new ArrayList<>();
        for (Object gpsInfoObj : gpsInfoList) {
            if (gpsInfoObj != null) {
                String gpsStr = redisTemplate.getStringSerializer().deserialize((byte[]) gpsInfoObj);
                GpsInfo gpsInfo = parseGpsInfo(gpsStr);
                result.add(gpsInfo);
            }
        }

        return result;
    }

    private GpsInfo parseGpsInfo(String gpsStr) {
        // 解析GPS信息的逻辑
        // ...
        return gpsInfo;
    }
}

4. 参考资料

  1. Redis官方文档https://redis.io/topics/pipelining

  2. Redis协议https://redis.io/topics/protocol

  3. Redis管道的优势和用途https://blog.csdn.net/u012439416/article/details/80291006

  4. Redis管道的实现原理https://juejin.cn/post/6844903955324334093

5. 源码地址

https://github.com/wangshuai67/icepip-springboot-action-examples
https://github.com/wangshuai67/Redis-Tutorial-2023

6. Redis从入门到精通系列文章

  • 《【Redis实践篇】使用Redisson 优雅实现项目实践过程中的5种场景》
  • 《Redis使用Lua脚本和Redisson来保证库存扣减中的原子性和一致性》
  • 《SpringBoot Redis 使用Lettuce和Jedis配置哨兵模式》
  • 《Redis【应用篇】之RedisTemplate基本操作》
  • 《Redis 从入门到精通【实践篇】之SpringBoot配置Redis多数据源》
  • 《Redis 从入门到精通【进阶篇】之三分钟了解Redis HyperLogLog 数据结构》
  • 《Redis 从入门到精通【进阶篇】之三分钟了解Redis地理位置数据结构GeoHash》
  • 《Redis 从入门到精通【进阶篇】之高可用哨兵机制(Redis Sentinel)详解》
  • 《Redis 从入门到精通【进阶篇】之redis主从复制详解》
  • 《Redis 从入门到精通【进阶篇】之Redis事务详解》
  • 《Redis从入门到精通【进阶篇】之对象机制详解》
  • 《Redis从入门到精通【进阶篇】之消息传递发布订阅模式详解》
  • 《Redis从入门到精通【进阶篇】之持久化 AOF详解》
  • 《Redis从入门到精通【进阶篇】之持久化RDB详解》
  • 《Redis从入门到精通【高阶篇】之底层数据结构字典(Dictionary)详解》
  • 《Redis从入门到精通【高阶篇】之底层数据结构快表QuickList详解》
  • 《Redis从入门到精通【高阶篇】之底层数据结构简单动态字符串(SDS)详解》
  • 《Redis从入门到精通【高阶篇】之底层数据结构压缩列表(ZipList)详解》
  • 《Redis从入门到精通【进阶篇】之数据类型Stream详解和使用示例》
    在这里插入图片描述大家好,我是冰点,今天的【实践篇】Redis管道操作优化性能。如果你有疑问或见解可以在评论区留言。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Revit SDK 介绍:TypeRegeneration 修改类型,更新文档 ValidateParameters 参数合法性验证

前言 这篇文章介绍两个例子&#xff0c;逻辑比较简单&#xff1a; TypeRegeneration 修改类型&#xff0c;更新文档ValidateParameters 参数合法性验证 内容 TypeRegeneration FamilyType 不是继承自 Element 的&#xff0c;而是独立于 Element 体系之外&#xff0c;直接从…

window.structuredClone()

先看下兼容性 1. 创建一个要克隆的对象。例如&#xff1a; const originalObj {name: John,age: 25,address: {city: New York,country: USA} };2. 调用structuredClone()方法克隆对象。例如&#xff1a; const clonedObj window.structuredClone(originalObj);3. clonedObj将…

软件安全研究(四)

文章目录 Fine-Grained Code Clone Detection with Block-Based Splitting of Abstract Syntax Tree文章结构IntroMotivationDefinitionSystemOverviewProcessingVerify Experimentexperimental settingsRQ1RQ2RQ3RQ4RQ5 Fine-Grained Code Clone Detection with Block-Based S…

MeterSphere压测,出现HttpHostConnectException

现象&#xff1a;MeterSphere更换压力机后&#xff0c;压测出现出现HttpHostConnectException 解决方案&#xff1a; net.ipv4.tcp_tw_reuse默认是0或者2&#xff0c;更改为1 net.ipv4.tcp_tw_reuse&#xff0c;表示是否允许重新应用处于TIME-WAIT状态的socket用于新的TCP连…

轻量级软件FastGithub实现稳定访问github

当我们想访问全球最大的“同性交友网站”https://github.com/ 时&#xff0c;总会出现无法访问的界面&#xff0c;令人非常苦恼&#xff1a;幸运的是&#xff0c;有一种轻量级的软件可以帮助我们稳定地访问GitHub&#xff0c;那就是FastGithub。 什么是FastGithub&#xff1f…

数据结构和算法(5):二叉树

树 向量允许通过下标或秩&#xff0c;在常数的时间内找到目标对象&#xff1b;然而&#xff0c;一旦需要对这类结构进行修改&#xff0c;那么无论是插入还是删除&#xff0c;都需要耗费线性的时间。 列表允许借助引用或位置对象&#xff0c;在常数的时间内插入或删除元素&…

去除pdf/word的水印艺术字

对于pdf中的水印如果无法去除水印&#xff0c;则先另存为word&#xff0c;然后再按下面办法处理即可&#xff1a; 查看宏&#xff0c;创建&#xff1a;删除艺术字 添加内容&#xff1a; Sub 删除艺术字()Dim sh As ShapeFor Each sh In ActiveDocument.ShapesIf sh.Type msoT…

用ASE制作地表积水效果

unity引擎制作实时刷下雨地面效果 大家好&#xff0c;我是阿赵。   之前在Unity引擎做了几种不同的效果&#xff0c;比如视差偏移、下雨效果、顶点颜色工具等。这一篇文章&#xff0c;将会把这几个效果合并在一起&#xff0c;做出一个混合积水地表的效果。这个几个shader的基…

基于elelemt-ui封装一个表单

子组件 searchForm <template><el-formref"form":model"value":rules"rules":label-width"labelWidth":inline"inline"><el-form-itemv-for"field in fields":key"field.slot":label&q…

JMeter基础 —— 使用Badboy录制JMeter脚本!

1、使用Badboy录制JMeter脚本 打开Badboy工具开始进行脚本录制&#xff1a; &#xff08;1&#xff09;当我们打开Badboy工具时&#xff0c;默认就进入录制状态。 如下图&#xff1a; 当然我们也可以点击录制按钮进行切换。 &#xff08;2&#xff09;在地址栏中输入被测地…

excel单元格多行文本的excel 提取 公式

excel单元格多行文本的excel 提取 公式 第一行&#xff1a; TRIM(MID(SUBSTITUTE(A$1,CHAR(10),REPT(" ",160)),ROW(A1)*160-159,160)) 第9行&#xff1a; TRIM(MID(SUBSTITUTE(A$1,CHAR(10),REPT(" ",160)),ROW(A9)*160-159,160)) Excel如何提取某一单元…

GRU实现时间序列预测(PyTorch版)

&#x1f4a5;项目专栏&#xff1a;【深度学习时间序列预测案例】零基础入门经典深度学习时间序列预测项目实战&#xff08;附代码数据集原理介绍&#xff09; 文章目录 前言一、基于PyTorch搭建GRU模型实现风速时间序列预测二、时序数据集的制作三、数据归一化四、数据集加载器…

Multi Query Attention Group Query Attention

Multi Query Attention(MQA)在2019年就被提出来了&#xff0c;用于推理加速&#xff0c;但在当时并没有受到很多关注&#xff0c;毕竟一张2080就能跑Bert-base了。随着LLM的大火&#xff0c;MQA所带来的收益得以放大。 思路 Multi Query Attention(MQA)跟Multi Head Attention…

win10 自带虚拟机软件 虚拟CentOS系统

win10 下使用需要虚拟一个系统&#xff0c;不需要额外安装VMware、Virtual box等软件。使用win10 自带虚拟机软件即可 步骤1 确保启动Hyper-V 功能启用 控制面板 -> 程序 -> 启用或关闭Windows功能 步骤 2 创建虚拟机 2.1 打开Typer-V 2.2 创建虚拟机 2.2.1 操作 -&g…

什么是数据湖?数据湖的概念及发展历程

随着云计算、社交媒体、物联网、短视频等新一代互联网技术的快速发展&#xff0c;数据的数量和复杂性不断增加。许多企业和组织已经积累了大量的各种类型的数据&#xff0c;对于如何存储和管理这些海量数据&#xff0c;以及如何高效地分析和利用这些数据&#xff0c;是每个组织…

数字IC设计笔试面试经典题(1-10)

1 基础知识 1.1 锁存器的结构 锁存器即Latch &#xff0c;数电中称之为电平触发的D触发器&#xff0c;也是D型锁存器&#xff0c;有电平触发器SR触发器改进得到&#xff0c;其工作特点是电平是有效电平&#xff08;高电平或者低电平&#xff09;期间&#xff0c;才接受信号并…

Vue中实现全景房看图3D

示例代码 安装photo-sphere-viewer yarn add -D photo-sphere-viewer 组件引入插件 import { Viewer } from photo-sphere-viewer; import photo-sphere-viewer/dist/photo-sphere-viewer.css; // 引入样式 import MarkersPlugin from photo-sphere-viewer/dist/plugins/marker…

一文读懂LCD、OLED、LED屏的区别以及透明液晶屏原理

参考文章科普&#xff5c;一文读懂LCD、LED和OLED 的区别 - 知乎 参考文章透明液晶显示屏的原理&#xff1f; - 知乎 一、LCD LCD是英文Liquid Crystal Display 的简称&#xff0c;指的是液晶显示屏。 主要想介绍下LCD透明屏方案&#xff1a; 所谓LCD透明屏&#xff0c;并…

Postman接口调用api

1.选择类型&#xff0c;输入URL 2.选择Basic Type 3.选择格式类型 文件类型 4.Send发送请求&#xff0c;获得返回

澄海区图书馆《乡村振兴战略下传统村落文化旅游设计》许少辉八一新著

澄海区图书馆《乡村振兴战略下传统村落文化旅游设计》许少辉八一新著