码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 单线程Jedis管道实现批量写入数据


    前言

            生产中的有些场景,我们经常需要大批量的往Redis中写入数据,如果我们采用单条循环写入的话,不仅效率低下,而且可能会出现频繁的创建和销毁redis连接,这些都是很不合理的.

            对此,我们可以采用Jedis的父类中的pipelined()方法获取管道,它可以实现一次性发送多条命令并一次性返回结果,这样就大量的减少了客户端与Redis的通信次数,可以有效的提高程序效率(但是,因为Redis要一次性返回所有结果,它会把这些结果都缓存起来,因此命令越多,缓存消耗的内存也会越大,具体还要视情况而定).此外Pipeline的原理是队列(先进先出),这样也保证了数据的顺序性.

    代码实现

    maven依赖

    1. <dependency>
    2. <groupId>org.springframework.bootgroupId>
    3. <artifactId>spring-boot-starter-data-redisartifactId>
    4. dependency>
    5. <dependency>
    6. <groupId>redis.clientsgroupId>
    7. <artifactId>jedisartifactId>
    8. dependency>
    9. <dependency>
    10. <groupId>org.springframework.bootgroupId>
    11. <artifactId>spring-boot-configuration-processorartifactId>
    12. <optional>trueoptional>
    13. dependency>

    配置文件配置redis

    1. redis.dateBase=1
    2. redis.url=192.168.3.111
    3. redis.password=123456
    4. redis.port=6379
    5. redis.maxTotal=200
    6. redis.maxWait=5000
    7. redis.maxIdle=5
    8. redis.minIdle=0
    9. redis.timeout=0

    读取配置文件内容并自动封装成实体类

    将redis的host,port,database封装到实体中。

    1. import lombok.Data;
    2. import org.springframework.boot.context.properties.ConfigurationProperties;
    3. import org.springframework.stereotype.Component;
    4. @ConfigurationProperties(prefix = "redis")
    5. @Component
    6. @Data
    7. public class RedisConfigProperties {
    8. private Integer dateBase;
    9. private String url;
    10. private String password;
    11. private Integer port;
    12. }

    Pipeline实现批量插入示例

    实现逻辑如下:

    1. 首先创建一个新的Jedis连接;
    2. 输入密码后指定database;
    3. 根据Jedis创建一个新的Pipeline;
    4. 调用hset方法批量写入;
    5. 批量写入完成后调用syncAndReturnAll方法统一写入redis;
    6. 最后关闭Jedis连接。
    1. @Component
    2. @Order(value = 2)
    3. public class MeteValueApplicationRunner implements ApplicationRunner {
    4. @Autowired
    5. RedisConfigProperties redisConfigProperties;
    6. @Override
    7. public void run(ApplicationArguments args) {
    8. Jedis jedis = new Jedis(redisConfigProperties.getUrl(), redisConfigProperties.getPort());
    9. // 输入密码
    10. jedis.auth(redisConfigProperties.getPassword());
    11. // 指定redis的database
    12. jedis.select(redisConfigProperties.getDateBase());
    13. Pipeline pipeline = jedis.pipelined();
    14. for (int i = 0; i < 10000; i++) {
    15. pipeline.hset("real_time_" + i, System.currentTimeMillis(), i);
    16. }
    17. List list = pipeline.syncAndReturnAll();
    18. jedis.disconnect();
    19. }
    20. }

    21. Pipeline批量设置过期时间

      使用pipeline的pexpire方法实现redis的key过期时间,源码如下:

      1. public Response pexpire(String key, long milliseconds) {
      2. this.getClient(key).pexpire(key, milliseconds);
      3. return this.getResponse(BuilderFactory.LONG);
      4. }

      可以看到传入参数为redis的key以及long类型的过期时间,过期时间可以通过org.springframework.data.redis.core.TimeoutUtils工具类中的toMillis方法得到,toMillis的源码如下:

      1. public static long toMillis(long timeout, TimeUnit unit) {
      2. return roundUpIfNecessary(timeout, unit.toMillis(timeout));
      3. }

      TimeUnit是JDK封装好的java.util.concurrent包下面的一个类,表示给定单元粒度的时间段。TimeUnit的所有颗粒度如下

      1. TimeUnit.DAYS //天
      2. TimeUnit.HOURS //小时
      3. TimeUnit.MINUTES //分钟
      4. TimeUnit.SECONDS //秒
      5. TimeUnit.MILLISECONDS //毫秒
      6. TimeUnit.MICROSSECONDS //微秒
      7. TimeUnit.NANOSSECONDS //纳秒

      示例:设置redis的过期为30天,代码如下:

      1. Integer timeout = 30;
      2. final TimeUnit unit = TimeUnit.DAYS;
      3. final long rawTimeout = TimeoutUtils.toMillis(timeout, unit);
      4. // 设置过期时间
      5. pipeline.pexpire("key", rawTimeout);

      上述通过Pipeline批量写入redis的代码改造如下:

      1. @Component
      2. @Order(value = 2)
      3. public class MeteValueApplicationRunner implements ApplicationRunner {
      4. @Autowired
      5. RedisConfigProperties redisConfigProperties;
      6. @Override
      7. public void run(ApplicationArguments args) {
      8. // 得到过期时间
      9. Integer timeout = 30;
      10. final TimeUnit unit = TimeUnit.DAYS;
      11. final long rawTimeout = TimeoutUtils.toMillis(timeout, unit);
      12. Jedis jedis = new Jedis(redisConfigProperties.getUrl(), redisConfigProperties.getPort());
      13. // 输入密码
      14. jedis.auth(redisConfigProperties.getPassword());
      15. // 指定redis的database
      16. jedis.select(redisConfigProperties.getDateBase());
      17. Pipeline pipeline = jedis.pipelined();
      18. for (int i = 0; i < 10000; i++) {
      19. pipeline.hset("real_time_" + i, System.currentTimeMillis(), i);
      20. pipeline.pexpire("real_time_" + i, rawTimeout);
      21. }
      22. List list = pipeline.syncAndReturnAll();
      23. jedis.disconnect();
      24. }
      25. }

      26. 相关阅读:
        【Java基础面试十三】、面向对象的三大特征是什么?
        Windows11更新后Chrome无法打开解决方案
        远程调用(REST和RPC)
        【推荐】SpringMVC与JSON数据返回及异常处理机制的使用
        Rust——包管理
        【算法】动态规划
        【Java毕设】基于SpringBoot实现新冠疫情统计系统(Idea+Navicat)
        Redis 的大 Key 对持久化的影响
        自学JavaScript第二天- JS 进阶: 对象 函数
        C++语法(9)---- 模拟string
      27. 原文地址:https://blog.csdn.net/qq_37634156/article/details/127571181
        • 最新文章
        • 沪漂五周年了:我越来越迷茫了
          Agentic Skill Routing 实战:别再把所有 Skill 塞进 AI Agent 上下文
          MySQL-Seconds_behind_master的精度误差
          [MAF预定义ChatClient中间件-03]CachingChatClient——利用缓存省钱省时间
          AI的至暗历史:从万众期待到被政府撤资,AI的两次死亡徘徊
          Agent OS :五种驯服不确定性的范式
          PortSwigger SQL注入LAB11
          数据库即时编译JIT
          [Begin]AI Learn Data Day 0
          深度学习进阶(二十七)现代 LLM 的核心架构设计其二:SwiGLU
        • 热门文章
        • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
          奉劝各位学弟学妹们,该打造你的技术影响力了!
          五年了,我在 CSDN 的两个一百万。
          Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
          面试官都震惊,你这网络基础可以啊!
          你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
          心情不好的时候,用 Python 画棵樱花树送给自己吧
          通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
          13 万字 C 语言从入门到精通保姆级教程2021 年版
          10行代码集2000张美女图,Python爬虫120例,再上征途
        小工具 小游戏
        Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1

        京公网安备 11010502049817号