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源碼

如有問題,歡迎評論或聯系我。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM