Redis16-批处理优化

news2024/9/23 3:12:00

目录

Pipeline

集群下的批处理


Pipeline

单个命令的执行流程:

N条命令的执行流程:

N条命令批量执行:

Redis提供了很多Mxxx这样的命令,可以实现批量插入数据,例如:

  • mset
  • hmset

利用mset批量插入10万条数据:

@Test
void testMxx() {
    String[] arr = new String[2000];
    int j;
    long b = System.currentTimeMillis();
    for (int i = 1; i <= 100000; i++) {
        j = (i % 1000) << 1;
        arr[j] = "test:key_" + i;
        arr[j + 1] = "value_" + i;
        if (j == 0) {
            jedis.mset(arr);
        }
    }
    long e = System.currentTimeMillis();
    System.out.println("time: " + (e - b));
}

注意:不要在一次批处理中传输太多命令,否则单条命令占用带宽过多,会导致网络阻塞

MSET虽然可以批处理,但是却只能操作部分数据类型,因此如果有对复杂数据类型的批处理需要,建议使用Pipeline  

@Test
void testPipeline() {
    // 创建管道
    Pipeline pipeline = jedis.pipelined();
    long b = System.currentTimeMillis();
    for (int i = 1; i <= 100000; i++) {
        // 放入命令到管道
        pipeline.set("test:key_" + i, "value_" + i);
        if (i % 1000 == 0) {
            // 每放入1000条命令,批量执行
            pipeline.sync();
        }
    }
    long e = System.currentTimeMillis();
    System.out.println("time: " + (e - b));
}

总结:

批量处理的方案:

  • 原生的M操作
  • Pipeline批处理

注意事项:

  • 批处理时不建议一次携带太多命令
  • Pipeline的多个命令之间不具备原子性

集群下的批处理

如MSET或Pipeline这样的批处理需要在一次请求中携带多条命令,而此时如果Redis是一个集群,那批处理命令的多个key必须落在一个插槽中,否则就会导致执行失败

串行化:

public class JedisClusterTest {

    private JedisCluster jedisCluster;

    @BeforeEach
    void setUp() {
        // 配置连接池
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(8);
        poolConfig.setMaxIdle(8);
        poolConfig.setMinIdle(0);
        poolConfig.setMaxWaitMillis(1000);
        HashSet<HostAndPort> nodes = new HashSet<>();
        nodes.add(new HostAndPort("192.168.150.101", 7001));
        nodes.add(new HostAndPort("192.168.150.101", 7002));
        nodes.add(new HostAndPort("192.168.150.101", 7003));
        nodes.add(new HostAndPort("192.168.150.101", 8001));
        nodes.add(new HostAndPort("192.168.150.101", 8002));
        nodes.add(new HostAndPort("192.168.150.101", 8003));
        jedisCluster = new JedisCluster(nodes, poolConfig);
    }

    @Test
    void testMSet() {
        jedisCluster.mset("name", "Jack", "age", "21", "sex", "male");

    }

    @Test
    void testMSet2() {
        Map<String, String> map = new HashMap<>(3);
        map.put("name", "Jack");
        map.put("age", "21");
        map.put("sex", "Male");
        //对Map数据进行分组。根据相同的slot放在一个分组
        //key就是slot,value就是一个组
        Map<Integer, List<Map.Entry<String, String>>> result = map.entrySet()
                .stream()
                .collect(Collectors.groupingBy(
                        entry -> ClusterSlotHashUtil.calculateSlot(entry.getKey()))
                );
        //串行的去执行mset的逻辑
        for (List<Map.Entry<String, String>> list : result.values()) {
            String[] arr = new String[list.size() * 2];
            int j = 0;
            for (int i = 0; i < list.size(); i++) {
                j = i<<2;
                Map.Entry<String, String> e = list.get(0);
                arr[j] = e.getKey();
                arr[j + 1] = e.getValue();
            }
            jedisCluster.mset(arr);
        }
    }

    @AfterEach
    void tearDown() {
        if (jedisCluster != null) {
            jedisCluster.close();
        }
    }
}

 Spring集群环境下批处理:

 @Test
    void testMSetInCluster() {
        Map<String, String> map = new HashMap<>(3);
        map.put("name", "Rose");
        map.put("age", "21");
        map.put("sex", "Female");
        stringRedisTemplate.opsForValue().multiSet(map);


        List<String> strings = stringRedisTemplate.opsForValue().multiGet(Arrays.asList("name", "age", "sex"));
        strings.forEach(System.out::println);

    }

原理:在RedisAdvancedClusterAsyncCommandsImpl 类中,首先根据slotHash算出来一个partitioned的map,map中的key就是slot,而它的value就是对应的对应相同slot的key对应的数据,通过 RedisFuture<String> mset = super.mset(op);进行异步的消息发送

@Override
public RedisFuture<String> mset(Map<K, V> map) {

    Map<Integer, List<K>> partitioned = SlotHash.partition(codec, map.keySet());

    if (partitioned.size() < 2) {
        return super.mset(map);
    }

    Map<Integer, RedisFuture<String>> executions = new HashMap<>();

    for (Map.Entry<Integer, List<K>> entry : partitioned.entrySet()) {

        Map<K, V> op = new HashMap<>();
        entry.getValue().forEach(k -> op.put(k, map.get(k)));

        RedisFuture<String> mset = super.mset(op);
        executions.put(entry.getKey(), mset);
    }

    return MultiNodeExecution.firstOfAsync(executions);
}

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

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

相关文章

vivado报错:file ended before end of clause

最近在学习Xilinx FPGA时&#xff0c;遇到 Vivado 报错如下图所示&#xff1a; 刚开始&#xff0c;看到错误是在第1行代码中出现的&#xff0c;我的第一反应是该行代码写错了&#xff0c;然后搜了搜语法&#xff0c;发现没错。 分析报错信息发现&#xff0c;该错误应该是和文件…

VScode + PlatformIO 和 Keil 开发 STM32

以前经常使用 KEIL 写 STM32 的代码&#xff0c;自从使用 VScode 写 ESP32 后感觉 KEIL 的开发环境不美观不智能了&#xff0c;后面学习了 VScode 开发 STM32 。 使用过程中发现 串口重定向在 KEIL 中可以用&#xff0c;搬到 VScode 后不能用&#xff0c;不用勾选 Use Micro LI…

SpringMVC 运行流程

SpringMVC 运行流程 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; SpringMVC的运行流程可概括为以下几个核心步骤&#xff1a; 流程图&#xff1a; #mermaid-svg-l1CeK9JwP5wRQjBL {font-family:"trebuchet ms",verdana,arial,…

医学图像分割新突破:6篇文献带你洞悉最前沿的医学AI技术|顶刊速递·24-08-14

小罗碎碎念 文献日推主题&#xff1a;人工智能在医学图像分割中的最新研究进展 今天这期文章信息量很大&#xff0c;并且不同的人看&#xff0c;获取的信息量也会差距很大。为了缩小这个差距&#xff0c;请在正式阅读前&#xff0c;记住小罗的一句话——模型学会了如何分割图像…

【Spark集群部署系列三】Spark StandAlone HA模式介绍和搭建以及使用

简介&#xff1a; Spark Standalone集群是Master-Slaves架构的集群模式&#xff0c;和大部分的Master-Slaves结构集群一样&#xff0c;存在着Master 单点故障&#xff08;SPOF&#xff09;的问题。 高可用HA 如何解决这个单点故障的问题&#xff0c;Spark提供了两种方案&#…

83.SAP ABAP从前台找字段所在表的两种方法整理笔记

目录 方法1&#xff1a;F1查看技术信息 F1 技术信息 方法2&#xff1a;ST05开启跟踪 Activate Trace Input and save data Deactivate Trace Display Trace 分析你想要的表 方法1&#xff1a;F1查看技术信息 从前台找一个屏幕字段所在表&#xff0c;一般通过按F1来查找…

Java Nacos与Gateway的使用

Java系列文章目录 IDEA使用指南 Java泛型总结&#xff08;快速上手详解&#xff09; Java Lambda表达式总结&#xff08;快速上手详解&#xff09; Java Optional容器总结&#xff08;快速上手图解&#xff09; Java 自定义注解笔记总结&#xff08;油管&#xff09; Jav…

【大数据】6:MapReduce YARN 初体验

目录 MapReduce & YARN 初体验 集群启停命令 一键启动脚本&#xff1a; 单进程启停 提交MapReduce任务到YARN执行 提交MapReduce程序至YARN运行 提交wordcount示例程序 提交求圆周率示例程序 拓展&#xff1a;蒙特卡罗算法求PI的基础原理 onte Carlo蒙特卡罗算法…

【MySQL 06】表的约束

文章目录 &#x1f308; 一、约束的概念&#x1f308; 二、空属性约束⭐ 1. 空值无法参与运算⭐ 2. 设置非空属性 &#x1f308; 三、默认值约束⭐ 1. 默认值使用案例⭐ 2. 同时设置 not null 和 default &#x1f308; 四、列描述约束&#x1f308; 五、zerofill 补零约束&…

贷齐乐漏洞复现+php特性绕过WAF

目录 一、环境搭建 1.将贷齐乐源码放入phpstudy中的www目录下 2.在phpstudy上创建网站&#xff1a; 3.在本地数据库中创建数据库--ctf&#xff0c;并创建users表&#xff1a; 4.往表中插入数据&#xff1a; 5.查看users表&#xff1a; 6.测试能否访问到数据库 二、源码分析…

力扣热题100_链表_234_回文链表

文章目录 题目链接解题思路解题代码 题目链接 234. 回文链表 给你一个单链表的头节点 head &#xff0c;请你判断该链表是否为 回文链表。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,2,1] 输出…

搭建MoneyPrinterTurbo,利用AI大模型,一键生成高清短视频实战

搭建MoneyPrinterTurbo&#xff0c;利用AI大模型&#xff0c;一键生成高清短视频 1.MoneyPrinterTurbo简介 只需提供一个视频 主题 或 关键词 &#xff0c;就可以全自动生成视频文案、视频素材、视频字幕、视频背景音乐&#xff0c;然后合成一个高清的短视频。 github地址&a…

【大模型从入门到精通19】开源库框架LangChain LangChain文档加载器1

目录 理解文档加载器非结构化数据加载器结构化数据加载器 使用文档加载器的实际指南设置和配置安装必要的包&#xff08;注意&#xff1a;这些包可能已经在你的环境中安装好了&#xff09;从 .env 文件加载环境变量从环境变量中设置 OpenAI API 密钥 在数据驱动的应用领域&…

企业如何组建安全稳定的跨国通信网络

当企业在海外设有分公司时&#xff0c;如何建立一个安全且稳定的跨国通信网络是一个关键问题。为了确保跨国通信的安全和稳定性&#xff0c;可以考虑以下几种方案。 首先&#xff0c;可以在分公司之间搭建虚拟专用网络。虚拟专用网络通过对传输数据进行加密&#xff0c;保护通信…

Java:jdk8以后开始接口新增的3种方法:default,private,static

文章目录 jdk8以后开始接口新增的方法默认方法&#xff1a;deafult私有方法private如何查看自己的jdk版本静态方法static 问题接口中不止有抽象方法为什么接口中的方法都是public为什么要增加这三种方法 jdk8以后开始接口新增的方法 默认方法&#xff1a;deafult 必须使用defa…

【CentOS 】DHCP 更改为静态 IP 地址并且遇到无法联网

文章目录 引言解决方式标题1. **编辑网络配置文件**&#xff1a;标题2. **确保配置文件包含以下内容**&#xff1a;特别注意 标题3. **重启网络服务**&#xff1a;标题4. **检查配置是否生效**&#xff1a;标题5. **测试网络连接**&#xff1a;标题6. **检查路由表**&#xff1…

思科默认路由配置2

#路由协议实现# #任务二默认路由配置2# #1配置计算机的IP地址、子网掩码和网关 #2配置Router-A的名称及其接口IP地址 Router(config)#hostname Router-A Router-A(config)#int g0/0 Router-A(config-if)#ip add 192.168.1.1 255.255.255.0 Router-A(config-if)#no shutdow…

全网最适合入门的面向对象编程教程:36 Python的内置数据类型-字典

全网最适合入门的面向对象编程教程&#xff1a;36 Python 的内置数据类型-字典 摘要&#xff1a; 字典是非常好用的容器&#xff0c;它可以用来直接将一个对象映射到另一个对象。一个拥有属性的空对象在某种程度上说就是一个字典&#xff0c;属性名映射到属性值。在内部&#…

【图形验证和AI智能及CHATGPT对抗影响的是用户体验】

验证码本质上自带一层答案的语义&#xff0c;这原本是天然的区分人和自动程序的地方&#xff0c;但在今日却未必&#xff0c;由于AI智能及CHATGPT的发展机器要识别也变得容易。 一 &#xff1a;攻防思路 黑产对于验证码图片答案的获取主要有两种手段——图片穷举破解和图片模…

[C++][opencv]基于opencv实现photoshop算法高反差保留

【测试环境】 vs2019 opencv4.8.0 【效果演示】 【核心代码实现】 Filter.hpp #ifndef OPENCV2_PHOTOS_FILTER_HPP_ #define OPENCV2_PHOTOS_FILTER_HPP_#include "opencv2/core.hpp" #include "opencv2/imgproc.hpp"namespace cv {class Filter { pu…