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/211690.shtml

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

相关文章

线程安全3--wait和notify

文章目录 wait and notify&#xff08;等待通知机制notify补充 wait and notify&#xff08;等待通知机制 引入wait notify就是为了能够从应用层面上&#xff0c;干预到多个不同线程代码的执行顺序&#xff0c;这里说的干预&#xff0c;不是影响系统的线程调度策略&#xff08…

uni-app应用设置 可以根据手机屏幕旋转进行 (横/竖) 屏切换

首先 我们打开项目的 manifest.json 在左侧导航栏中找到 源码视图 然后找到 app-plus 配置 在下面加上 "orientation": [//竖屏正方向"portrait-primary",//竖屏反方向"portrait-secondary",//横屏正方向"landscape-primary",//横屏…

第57天:django学习(六)

模版之过滤器 语法&#xff1a; {{obj|filter__name:param}} 变量名字|过滤器名称&#xff1a;变量 default 如果一个变量是false或者为空&#xff0c;使用给定的默认值。否则&#xff0c;使用变量的值。例如&#xff1a; {{ value|default:"nothing"}} length …

IDEA启动应用时报错:错误: 找不到或无法加载主类 @C:\Users\xxx\AppData\Local\Temp\idea_arg_filexxx

IDEA启动应用时报错&#xff0c;详细错误消息如下&#xff1a; C:\devel\jdk1.8.0_201\bin\java.exe -agentlib:jdwptransportdt_socket,address127.0.0.1:65267,suspendy,servern -XX:TieredStopAtLevel1 -noverify -Dspring.output.ansi.enabledalways -Dcom.sun.management…

基于以太坊的智能合约开发Solidity(事件日志篇)

//声明版本号&#xff08;程序中的版本号要和编译器版本号一致&#xff09; pragma solidity ^0.5.17; //合约 contract EventTest {//状态变量uint public Variable;//构造函数constructor() public{Variable 100;}event ValueChanged(uint newValue); //事件声明event Log(…

ElasticSearch之cat plugins API

命令样例如下&#xff1a; curl -X GET "https://localhost:9200/_cat/plugins?vtrue&pretty" --cacert $ES_HOME/config/certs/http_ca.crt -u "elastic:ohCxPHQBEs5*lo7F9"执行结果输出如下&#xff1a; name component version…

class064 Dijkstra算法、分层图最短路【算法】

class064 Dijkstra算法、分层图最短路【算法】 算法讲解064【必备】Dijkstra算法、分层图最短路 code1 743. 网络延迟时间 // Dijkstra算法模版&#xff08;Leetcode&#xff09; // 网络延迟时间 // 有 n 个网络节点&#xff0c;标记为 1 到 n // 给你一个列表 times&…

法律服务网站建设效果如何

律师事务所及法律知识咨询机构等往往是众多人群需求的服务&#xff0c;服务多样化及内容多元化&#xff0c;市场中也有大量品牌&#xff0c;在实际消费服务中大多以本地事务所为主&#xff0c;而线上咨询服务则一般没有区域限制&#xff0c;同行增多及人们知识获取渠道增加&…

C++-引用和指针区别

文章目录 1.变量的组成2.指针2.1 定义2.2 使用指针操作变量2.3 为什么使用指针 3.引用3.1 定义3.2 引用注意事项 4.引用和指针的区别 1.变量的组成 变量的组成&#xff1a;变量地址&#xff0c;变量名&#xff0c;变量值 例&#xff1a; int i 12;2.指针 2.1 定义 指针用于存…

如何为游戏角色3D模型设置纹理贴图

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 当谈到游戏角色的3D模型风格时&#xff0c;有几种不同的风格&#xf…

Mybatis中的查询操作

单表查询 单表查询在《初始Mybatis》中已经介绍过&#xff0c;这里就不在介绍了。咱们这里只说单表查询中的“like查询”。like查询单独使用#{}报错 <select id"selectByKeyword" resultType"com.example.demo.entity.Userinfo">select * from use…

计网Lesson8 - NAT技术与链路层概述

文章目录 NAT 技术1. 因特网的接入方式2. 公网和私网3. NAT 技术 链路层1. 数据链路层概述2. 数据链路层的三个问题2.1 封装成帧2.2 透明传输2.3 差错检测 NAT 技术 1. 因特网的接入方式 光猫将电信号转换为数字信号发送给路由器 光纤入户 光纤传递的就是数字信号&#xff0c…

python+pytest接口自动化(12)-自动化用例编写思路 (使用pytest编写一个测试脚本)

经过之前的学习铺垫&#xff0c;我们尝试着利用pytest框架编写一条接口自动化测试用例&#xff0c;来厘清接口自动化用例编写的思路。 我们在百度搜索天气查询&#xff0c;会出现如下图所示结果&#xff1a; 接下来&#xff0c;我们以该天气查询接口为例&#xff0c;编写接口测…

错题总结(三)

1.写代码将三个整数数按从大到小输出。 例如&#xff1a; 输入&#xff1a;2 3 1 输出&#xff1a;3 2 1 int main() {int a 0;int b 0;int c 0;int tep 0;scanf("%d%d%d", &a, &b, &c);if (a < b){tep a;a b;b tep;}if (b < c){tep b…

每日一练2023.12.9—— 矩阵A乘以B【PTA】

题目链接&#xff1a;L1-048 矩阵A乘以B 题目要求&#xff1a; 给定两个矩阵A和B&#xff0c;要求你计算它们的乘积矩阵AB。需要注意的是&#xff0c;只有规模匹配的矩阵才可以相乘。即若A有Ra​行、Ca​列&#xff0c;B有Rb​行、Cb​列&#xff0c;则只有Ca​与Rb​相等时&a…

Linux Shell 基础命令

Linux 是一个开源的操作系统&#xff0c;其命令行界面是它的重要组成部分。在这个界面下&#xff0c;Shell 是一个能够与操作系统进行交互的工具。Shell 是一种程序&#xff0c;它能够接收用户输入的命令&#xff0c;并将这些命令发送到操作系统中进行处理。 在 Linux 中&…

Docker实战笔记 三 Docker私有库

1.拉取私有库image rootcenots-7.5:/root#docker pull registry Using default tag: latest latest: Pulling from library/registry c926b61bad3b: Pull complete 5501dced60f8: Pull complete e875fe5e6b9c: Pull complete 21f4bf2f86f9: Pull complete 98513cca25bb: P…

VINS-MONO代码解读5----vins_estimator(marginalization部分)

文章目录 0. 前言1.1 Marginalization Pipiline 1. marg factor构建1.1 变量及维度理解1.2 IMUFactor1.3 ProjectionTdFactor(ProjectionFactor)1.4 MarginalizationFactor( e p e_p ep​推导更新&#xff0c;FEJ解决的问题)1.4.1 先验残差的更新1.4.2 先验Jacobian的更新 2. R…

windows install git

refer: https://developers.weixin.qq.com/miniprogram/dev/devtools/wechatvcs.html https://blog.csdn.net/weixin_40228200/article/details/128451324 在使用小程序的时候&#xff0c;需要初始化项目&#xff0c;需要注册Git账号 1.在本地确认cmd没有安装Git,进入Git官网…

docker:安装mysql以及最佳实践

文章目录 1、拉取镜像2、运行容器3、进入容器方式一方式二方式三容器进入后连接mysql和在宿主机连接mysql的区别 持久化数据持久化数据最佳实践 1、拉取镜像 docker pull mysql2、运行容器 docker run -d -p 3307:3306 --name mysql-container -e MYSQL_ROOT_PASSWORD123456 …