redis中使用pipeline

在操作数据库时,为了加快程序的执行速度,在新增或更新数据时,可以通过批量提交的方式来减少应用和数据库间的传输次数;在redis中也有这样的技术实现批量处理,也就是管道——Pipeline。它也是通过批量提交数据的方式来实现的,将要执行的redis命令提交到pipeline中,pipeline一次性的将数据发送给服务器,服务器再逐条执行命令。在执行命令过程中不是原子性的,可以插入其他命令执行。
下面演示在jedis中使用管道:

<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>4.3.0</version>
</dependency>

先通过一个测试示例代码看一下运行时间差异:

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Pipeline;import java.time.Duration;public class JedisUtil {/*** 连接地址*/private String host;/*** 连接端口号*/private int port;/*** 密码*/private String password;/*** 连接池*/private JedisPool jedisPool;/*** 连接初始化* @param host* @param port* @param password*/public JedisUtil(String host, int port, String password) {this.host = host;this.port = port;this.password = password;JedisPoolConfig config = new JedisPoolConfig();config.setMaxTotal(256);config.setMaxIdle(256);config.setMinIdle(1);config.setMaxWait(Duration.ofMillis(300));if(password != null && !"".equals(password)) {jedisPool = new JedisPool(config, host, port, 500, password);} else {jedisPool = new JedisPool(config, this.host, this.port, 500);}}/*** 关闭连接池*/public void close() {if(jedisPool != null && !jedisPool.isClosed()) {jedisPool.clear();jedisPool.close();}}/*** 获取连接* @return*/public Jedis getJedis() {if(jedisPool != null && !jedisPool.isClosed()) {return jedisPool.getResource();}return null;}/*** 归还jedis对象* @param jedis*/public void returnJedis(Jedis jedis) {if(jedis != null) {jedis.close();}}public static void main(String[] args) {// 获取jedis连接JedisUtil util = new JedisUtil("192.168.56.101", 6379, "");Jedis jedis = util.getJedis();// 设置键的数量:100万int KEY_COUNT = 1_000_000;// 普通方式setlong start1 = System.currentTimeMillis();for(int i = 0; i < KEY_COUNT; i++) {jedis.set("key1_" + i, "value1_" + i);}System.out.println("use time : " + (System.currentTimeMillis() - start1) + "ms");// 清理数据库的key,线上系统不要使用jedis.flushDB();// 使用管道setlong start2 = System.currentTimeMillis();Pipeline pipeline = jedis.pipelined();int num = 0;for(int i = 0; i < KEY_COUNT; i++) {pipeline.set("key2_" + i, "value2_" + i);if(num++ >= 200) {
//                pipeline.syncAndReturnAll();pipeline.sync();pipeline.close();pipeline = jedis.pipelined();num = 0;}}if(num != 0) {pipeline.syncAndReturnAll();pipeline.close();}System.out.println("pipeline : " + (System.currentTimeMillis() - start2) + "ms");// 清理数据库的key,线上系统不要使用jedis.flushDB();}
}

上面的代码运行两次,调整先后顺序分别运行,得到的运行时间:

use time : 79297ms
pipeline : 2036mspipeline : 1747ms
use time : 85078ms

可以看到两次运行的时间差异还是非常明显的,基本上差距40~50倍,再实际运行时可以多次测试并调整每次pipeline提交命令的条数,找到每次提交数据时性能最好的数据条数。pipeline每次提交数据量不宜过多,太多的命令一次提交会导致客户端等待结果时间比较长,也会让连接的缓冲区数据量过大。

pipeline本身没有过多内容需要讲解,下面介绍一下如何在redisTemplate中使用pipeline,redisTemplate中已经提供了对应方法executePipelined()可以直接调用,它支持两个类型的参数:RedisCallback更接近redis原生命令,但是需要自己将键和值都转换为字节码传递过去;SessionCallback对操作进行了封装,可以根据操作不同的数据类型进行转换,方便api使用。

List<Object> datas = redisTemplate.executePipelined(new RedisCallback<Object>() {@Overridepublic Object doInRedis(RedisConnection connection) throws DataAccessException {connection.set("key1".getBytes(StandardCharsets.UTF_8), "value1".getBytes(StandardCharsets.UTF_8));connection.set("key2".getBytes(StandardCharsets.UTF_8), "value2".getBytes(StandardCharsets.UTF_8));connection.set("key3".getBytes(StandardCharsets.UTF_8), "value3".getBytes(StandardCharsets.UTF_8));connection.set("key4".getBytes(StandardCharsets.UTF_8), "value4".getBytes(StandardCharsets.UTF_8));connection.set("key5".getBytes(StandardCharsets.UTF_8), "value5".getBytes(StandardCharsets.UTF_8));connection.set("key6".getBytes(StandardCharsets.UTF_8), "value6".getBytes(StandardCharsets.UTF_8));connection.get("key1".getBytes(StandardCharsets.UTF_8));// 这里必须返回null,在 connection.closePipeline() 时覆盖原来的返回值,所以返回值没有必要设置,设置会报错return null;}
});
List<Object> datas = redisTemplate.executePipelined(new SessionCallback<Object>() {@Overridepublic <K, V> Object execute(RedisOperations<K, V> operations) throws DataAccessException {ValueOperations<String, String> op1 = (ValueOperations<String, String>) operations.opsForValue();op1.set("key7", "value7");op1.set("key8", "value8");op1.get("key2");SetOperations<String, String> op2 = (SetOperations<String, String>) operations.opsForSet();op2.add("set_demo", "value1", "value2", "value3");op2.randomMember("set_demo");return null;}
});

pipeline非常显著的提升系统性能,对于redis这种内存数据库,每天的请求量会非常高,对于系统优化来说,管道技术的使用应该成为代码的一个优化点。

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

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

相关文章

FPS和SFTP的速度哪个更快?区别在哪里?

在互联网时代&#xff0c;我们频繁需要传输大文件&#xff0c;如视频、音乐、图片和文档等。这些文件不仅占用大量空间&#xff0c;而且传输时间长。确保传输过程的安全性和稳定性&#xff0c;以防文件被窃取或损坏成为重要考虑因素。在选择传输方式时&#xff0c;FPS和SFTP是两…

力扣-435.无重叠空间

利用快排&#xff0c;对数组右边界进行排序。 用一个变量记录区间的分割点&#xff0c;然后用这个分割点去和下一个区间做比较&#xff0c;如果没有重叠&#xff0c;更新右边界&#xff0c;没有重叠的区间个数加一。 然后更新右边界&#xff0c;继续进行比较。 最后用总区间…

Databend 如何利用 GPT-4 进行质量保证

背景 在数据库行业&#xff0c;质量是核心要素。 Databend 的应用场景广泛&#xff0c;特别是在金融相关领域&#xff0c;其查询结果的准确性对用户至关重要。因此&#xff0c;在快速迭代的过程中&#xff0c;如何确保产品质量&#xff0c;成为我们面临的重大挑战。 随着 Da…

leaflet:经纬度坐标转为地址,点击鼠标显示地址信息(137)

第137个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中将经纬度坐标转化为地址,点击鼠标显示某地的地址信息 。主要利用mapbox的api将坐标转化为地址,然后在固定的位置显示出来。 直接复制下面的 vue+leaflet源代码,操作2分钟即可运行实现效果 文章目录 示…

Springboot 项目关于版本升级到 3.x ,JDK升级到17的相关问题

由于spring 停止对2.x 版本的维护&#xff0c;以及 jdk 频繁发布等客观因素&#xff0c;现需要对已有springboot 工程做一次全面升级&#xff1b;已因对市面上第三方等依赖库的兼容问题&#xff1b; 现有工程使用哥技术栈是版本&#xff1a; freemarker &#xff1a;2.3.32 spr…

Segment Anything--SAM框架(二)

文章目录 prologuepaper && codeImage encoderPrompt encoderLightweight mask decoderMaking the model ambiguity-aware prologue 没什么事&#xff0c;写一写SAM的paper中关于模型框架的部分和实际代码部分。 paper && code SAM有三个组件&#xff0c;如图…

要求CHATGPT高质量回答的艺术:提示工程技术的完整指南—第 9 章:种子词提示

要求CHATGPT高质量回答的艺术&#xff1a;提示工程技术的完整指南—第 9 章&#xff1a;种子词提示 种子词提示是一种通过提供特定种子词或短语来控制 ChatGPT 输出的技术。 种子词提示符的提示公式是种子词或短语&#xff0c;然后是指令 “请根据以下种子词生成文本”。 示…

【PTA题目】7-31 前世档案 分数 20

7-31 前世档案 分数 20 全屏浏览题目 切换布局 作者 陈越 单位 浙江大学 网络世界中时常会遇到这类滑稽的算命小程序&#xff0c;实现原理很简单&#xff0c;随便设计几个问题&#xff0c;根据玩家对每个问题的回答选择一条判断树中的路径&#xff08;如下图所示&#xff09…

【若依系列】1.项目修改成自己包名并启动服务

项目下载地址&#xff1a; 分离版本 https://gitee.com/y_project/RuoYi-Vue 修改工具下载 https://gitee.com/lpf_project/common-tools 相关截图&#xff1a; 1.项目结构&#xff1a; 2.修改包名工具&#xff1a; 工具截图&#xff0c;根据对应提示自定义修改即可&#x…

【JS】检索树结构,并返回结果节点的路径与子节点

【JS】检索树结构&#xff0c;并返回结果节点的路径与子节点 需求代码效果展示 需求 一个树结构&#xff0c;需要添加条件检索功能&#xff0c;检索结果依然是一个树结构&#xff0c;包含所有的符合要求的节点&#xff0c;以及他们到根节点的路径&#xff0c;与他们的子节点 …

Spring Boot基础

文章目录 一、Spring Boot1. Spring的缺点2. Spring Boot 改变了什么3. Spring Boot项目搭建4. 热部署5. 依赖管理6. 代码生成器7. 日志8. 日期转换9. 接口文档10. 打包部署11. 自动装配 一、Spring Boot 1. Spring的缺点 在Spring Boot出现以前&#xff0c;使用Spring框架的…

二叉树OJ题之三

哈喽伙伴们&#xff0c;有一段时间没更新博客了&#xff0c;主要是这段时间要准备学校的期末考试&#xff0c;所以没有把部分时间分给博客&#xff0c;今天我们一起去接着看二叉树递归有关的OJ题&#xff0c;今天我们要学习的是 判断相同的树&#xff0c;力扣题目--100 &…

JSONArray添加JSONObject数据组装后,toString()发现值有{“$ref“:“$[0]“}乱码问题

出现这个问题是FastJson的循环引用造车的&#xff0c;可以手动设置取消FastJson的循环引用的检查。代码如下&#xff1a; JSONArray oaArr new JSONArray(); //取消JSON循环引用检查 String s JSON.toJSONString(oaArr, SerializerFeature.DisableCircularReferenceDetect)…

算法通关村第十四关|黄金挑战|数据流的中位数

数据流的中位数 原题&#xff1a;力扣295. 设计一种数据结构可以支持添加整数和返回中位数的操作。 之前写过找中间用两个堆&#xff0c;这道题就可以使用一个大顶堆和一个小顶堆。 大顶堆存储比较小的元素&#xff0c;小顶堆存储比较大的元素。 class MedianFinder {Prio…

quickapp_快应用_DOM节点

DOM $element获取某元素的宽高 $element $element是通用方法(提供给所有组件调用的方法) 获取指定 id 的组件 dom 对象&#xff0c;如果没有指定 id&#xff0c;则返回根组件 dom 对象用法。 this.$element(id名)获取某元素的宽高 const element this.$element(元素id名)…

龙芯loongarch64服务器编译安装pytorch

前言 PyTorch是一个开源的Python机器学习库,基于Torch,用于自然语言处理等应用程序,它是一个基于Python的可续计算包。在通过龙芯开源仓库下载依赖包后,执行import torch后,发现其中安装的"pytorch"就无法正常使用,这里就演示下pytorch整个编译流程。 1、环境准…

supervisor杀死不掉程序的问题分析

项目场景&#xff1a; supervisor可以说是linux上大名鼎鼎的守护进程工具了&#xff0c;它的易用性在我所有用过的工具里算是排名前列的。但在使用过程中也不免会出一些问题&#xff0c;很多都是设置错误导致的。 问题描述 使用java启动一个jar&#xff0c;调用stop的时候jar…

推荐一款Excel快速加载SQL的插件,方便又好用

如果告诉你只需要双击一下&#xff0c;SQL数据库中存放在表里面的数据&#xff0c;就能加载到你的Excel中&#xff0c;你想不想要&#xff1f; 今天给大家推荐一款好用的Excel插件&#xff0c;安装简单&#xff0c;使用方便&#xff0c;是经常使用SQL数据库的不二。 这款插件…

Web开发学习HTTP协议、通过浏览器控制台学习HTTP协议。

文章目录 HTTP协议1.HTTP协议是什么&#xff1f;2.HTTP协议的特点3.什么是URL?4.通过浏览器控制台学习HTTP协议Request Headers请求数据格式说明Response Headers请求数据格式说明 5.HTTP工作原理 HTTP协议 1.HTTP协议是什么&#xff1f; HTTP协议是一种超文本传输协议&…

前端实现主题(深色模式)切换的几种方案

方案一&#xff1a;link 动态引入 通过改变link 标签的 href 属性实现动态修改样式&#xff08;暂不推荐这种方案&#xff09; 优点&#xff1a;实现了按需加载&#xff0c;提高了性能&#xff1b; 缺点&#xff1a;动态加载样式文件&#xff0c;可能会因为网络问题导致样式…