zoukankan      html  css  js  c++  java
  • jedis中rpop函数操作删除的简要分析

    jedis中rpop操作删除的简要分析

    学习使人进步,为了提升性能,保证HA,运维想把redis也弄成redis集群,陪他玩的任务自然就落在了最近有点闲的我的身上。在测试过程中需要模拟很多场景,其中一个场景是:用户使用rpop读取list信息时,未传输结束的时候,主redis突然发生问题,进入重连。这条数据是否会被删除?或是删除一部分?亦或者是完全没有删除操作?这引起我的思考。

    如果文章内容有问题,欢迎评论或与我进行讨论(请注明原因):

    mail: wgh0807@qq.com
    微信: hello-wgh0807
    qq: 490536401

    结论

    如果在传输过程中突然redis异常,redis不会进行删除操作。rpop将value值作为一个整体,不会作为字节流边删边传。具体流程见下文。

    实验过程:

    1. 编写了一个简单的java Application,用于获取redis中List类型对象的每一项value。

      private void redisClusterTesr() {
              String host = "localhost";
              Integer port = 6379;
              String password = "test";
              String name = "Thread1";
              
              // 和redis服务器建立连接
              Jedis jedis = new Jedis(host, port); 
              try {
                  jedis.auth(password);
              } catch (JedisConnectionException e) {
                  System.err.println(name + "无法连接至目的主机!" + host + ":" + port);
                  return;
              } catch (JedisDataException e) {
                  System.err.println(name + "密码错误,登陆失败!" + e.getMessage());
                  return;
              }
              System.out.println();
              
              // 获取存储的数据并输出
              long size = jedis.llen(name);
              List<String> list = new ArrayList<>();
      
              // 循环进行rpop,抛出每个
              for (int i = 0; i < size; i++) {
                  try {
                      String str = jedis.rpop(name);
                      list.add(str);
                      System.out.println(name+" 获取成功,ID:"+i);
                  } catch (JedisConnectionException e) {
                      System.err.println(name + "连接已断开,正在准备重新连接");
                      boolean result = false;
                      for (int j = 0; j < 10; j++) {
                          jedis.close();
                          jedis = new Jedis(host, port);
                          try {
                              jedis.auth(password);
                              System.err.println(name + "第 /10次重新连接:连接成功");
                              i--;
                          } catch (JedisConnectionException e1) {
                              System.err.println(name + "第 /10次重新连接:连接失败");
                          }
                      }
                  }
              }
              System.out.println("finish,size: "+list.size());
              System.out.println(Arrays.toString(list.toArray()));
          }
      
    2. 在其中第28行,即String str = jedis.rpop(name); 处增加断点

    3. 正常执行(resume,idea快捷键F9)一至两项后,选择Step into 按钮查看下层实现代码(idea快捷键F7)。

    4. 观察代码,总结流程

    rpop流程图

    redis-rpop流程

    ps:基本就是这样,若传输时网络异常,没有传输完成,将抛出IO异常(可能被上层捕获并转换为JedisConnectionException,这里没有注意)。不会发送确认并删除请求。

    总结

    这个问题虽然解决了,但jedis和redis对我而言依旧神秘,我编写的测试数据为30线程*2000w条数据,共6亿条数据,每条数据5k,在不到30s便挤爆了32G服务器的50G硬盘,且停止运行的原因是磁盘不足,而不是内存不足。

    redis的高效率超出了我的想象,不是一个简简单单的‘小工具’。有机会一定要读一下他的源代码,一定有所收获。

    参考文献:

    jedis源码

    如有问题,欢迎评论或联系我。

  • 相关阅读:
    基于Twisted的简单聊天室
    小学题的python实现
    初识Go(8)
    初识Go(7)
    初识Go(6)
    初识Go(5)
    初识Go(4)
    初识Go(3)
    初识Go(2)
    初识Go(1)
  • 原文地址:https://www.cnblogs.com/wgh0807/p/11399030.html
Copyright © 2011-2022 走看看