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

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

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

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

mail: [email protected]
微信: 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源码

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

猜你喜欢

转载自www.cnblogs.com/wgh0807/p/11399030.html
今日推荐