1. 程式人生 > >redis性能測試

redis性能測試

code get simple 秒級 sts hub 個人 手動 log

  一 測試目的  

  開發需要為了尋求系統最優的解決方案,但是網上關於性能方面的資料並不是很多,沒有很明顯的數據說明,只是一般的結論性判斷不好說什麽,所以這裏自己重新測試整理了一番.

  二 測試環境

  主機主機ip為...86,系統為64位win7,4g內存,雙核2.93GHz,2.94GHz,從機ip為...59,系統為64位win7,6g內存,雙核2.93GHz,2.94GHz.

  雙機在同一個局域網,開啟了密碼驗證,主從配置通過配置文件直接配置後,從機配置為不可寫入.

  開發工具為Eclipse Indigo Service Release 1,java環境為32位java1.6 .Redis為Redis-x64-3.0.504版本,redis架包為jedis-2.9.0.jar.

  三 開始測試

  3.1 一般測試

  3.1.1 測試方法:

  直接手動操作,針對redis進行各種狀況的模擬.主要涉及到的工具有redis,management tool for redis.cmd窗口.

  3.1.2 測試過程:

  主從均關閉,開啟主redis導入少量數據到主redis,開啟從redis,從redis有一樣的數據.
  主從均關閉,開啟從redis,刪除少量數據到從redis(management tool for redis),開啟主redis,主redis數據不變化,刷新從,從redis恢復原來的數據.
  主從均開啟,操作部分數據到主redis,從redis有同樣的數據,

  主從均開啟,刪除部分數據(management tool for redis)到從redis,主redis原有數據不會變動,再次刷新從redis發現更改未生效,cmd操作從機發現無法進行寫入,
  主從均開啟,主導入部分數據之後從有同樣數據,關閉主之後再次開啟,主的數據恢復.
  主從均開啟,主導入部分數據之後從有同樣數據,關閉從之後再次開啟,從的數據恢復.
  主從均開啟,主導入部分數據之後從有同樣數據,關閉主之後,刪除本地文件dump.rdb,然後主再次開啟,主的數據沒有,從的數據直接同步為主的沒有數據狀態,cmd操作從機發現無法進行寫入.
  主從均開啟,主導入部分數據之後從有同樣數據,關閉從之後,刪除本地文件dump.rdb,再次開啟從,從的數據恢復.

  3.1.3 測試結論:

  主機開啟之後,首先從dump文件恢復數據,之後會不定期同步數據到磁盤的dump.rbd文件,關閉之後再起開啟會再次直接從dump恢復數據,如果沒有這個文件會造成數據清空的狀況.

  從開啟之後,會從dump文件回復數據,之後查找網絡的主機,找到之後進行一個備份編碼的對比,如果相同就進行局部同步,不同就進行全同步--即發送全同步請求之後,直接獲取到從機的dump文件,之後直接清空從機的數據之後從文件恢復.

  3.2代碼測試

  3.2.1 寫入數據測試

  3.2.1.1 操作方法

  通過寫程序對數據的作進行寫入操作並進行分析.

  3.2.1.2 操作代碼

  直接通過jedis代碼一個個寫入數據:

private static void EngineDataCreat() {
        Jedis jedis = new Jedis(rip, rport);
        jedis.auth(rpassword);
        System.out.println("Server is running: " + jedis.ping()
                + " Start to write!");
        jedis.flushAll();
        MyTimeUtil mt = new MyTimeUtil();

        for (int j = 0; j < 1; j++) { //寫入的次數,多次以求取平均值
            mt.start();
            for (int i = 0; i < 1000; i++) {
                for (PlanProprity e : PlanProprity.values()) {
                    jedis.set("China_beijing_plane:" + i + ":" + e,
                            " " + mt.getTime());
                }
            }
            for (int i = 0; i < 1000; i++) {
                for (CarProprity e : CarProprity.values()) {
                    jedis.set("China_hubei_car:" + i + ":" + e,
                            " " + mt.getTime());
                }
            }
       mt.endAndDisp(); } System.out.println(
"Server is running: " + jedis.ping() + "Write finished!"); }

  直接通過jedis管道進行數據的批量寫入:

private static void EngineDataCreatByPipe() {
        Jedis jedis = new Jedis(rip, rport);
        jedis.auth(rpassword);
        System.out.println("Server is running: " + jedis.ping()
                + " Start to write!");
        jedis.flushAll();
        MyTimeUtil mt = new MyTimeUtil();
        
        for (int j = 0; j < 1; j++) {
            mt.start();
            Pipeline pipeline = jedis.pipelined();
            
            for (int i = 0; i < 1000; i++) {
                for (PlanProprity e : PlanProprity.values()) {
                    pipeline.set("China_beijing_plane:" + i + ":" + e,
                            " " + mt.getTime());
                }
            }
            for (int i = 0; i < 1000; i++) {
                for (CarProprity e : CarProprity.values()) {
                    pipeline.set("China_hubei_car:" + i + ":" + e,
                            " " + mt.getTime());
                }
            }
            pipeline.syncAndReturnAll();
            mt.endAndDisp();
            
        }
        System.out.println("Server is running: " + jedis.ping()
                + "Write finished!");
    }

  上面的那個計時的類是自己寫的一個工具,可以參考下:

   http://www.cnblogs.com/wangkun1993/p/7199146.html 自寫時間小工具類

  rip就是主機和從機的ip號,rport是端口好,rpassword是驗證的密碼.

  遍歷的兩個是兩個大小為十的枚舉類型:

  

  enum PlanProprity {
        PSpeed, PPrice, PLength, PHeight, PWidth, PCapacity, PMore1, PMore2, PMore3, PMore4
    };

    enum CarProprity {
        CSpeed, CPrice, CMOre1, CMOre2, CMOre3, CMOre4, CMOre5, CMOre6, CMOre7, CMOre
    }

  3.2.1.3 操作結果

  主單個寫入10000條數據耗時: 24454ms 28491ms 45811ms 38017ms 22528ms 17845ms 18502ms 18079ms

  主通過管道一次寫入10000數據耗時: 388ms 503ms 1288ms 922ms 419ms 341ms 342ms 325ms
  寫入20w數據4356ms
  寫入200w數據34121ms
  從機無法寫入數據.
  從更改為主後測試遠程寫入數據:
  從單個寫入10000條數據耗時 6528ms 26953ms 32541ms 24982ms 22493ms 29789ms 31062ms
  從通過管道一次寫入10000數據耗時 227ms 753ms 599ms 387ms 508ms 531ms 507ms

  3.2.1.4 結果分析

  通過對比發現數據的寫入速度通過管道實現效率得到了極大的提升,電腦的處理速度和網絡的連通率對於遠程操作的影響還是比較大的.

  3.2.2 讀取數據測試

  3.2.2.1 操作方法

  通過代碼對redis進行數據的獲取操作.

  3.2.2.2 操作代碼

  直接通過get函數單個獲取數據操作:

private static void getDate() {
        Jedis jedis = new Jedis(rip, rport);
        jedis.auth(rpassword);
        System.out.println("Server is running: " + jedis.ping());
        // jedis.flushAll();
        MyTimeUtil mt = new MyTimeUtil();

        String strSaveDir = "d:\\edata\\";
        String fileName = "BAIHEYUAN_HW_"
                + new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date())
                + ".DJ";
        // String fileName="BAIHEYUAN_HW_20161122_0030.DJ";
        MyFileUtil mf = new MyFileUtil();
        String fileContent = null, tcont = null;
        String dateType = "China_beijing_plane";
        System.out.println("Start to get data");
        for (int j = 0; j < 1; j++) {
            fileContent = null;

            mt.start();
            for (int i = 0; i < 1000; i++) {
                for (PlanProprity e : PlanProprity.values()) {
                    tcont = jedis.get(dateType + ":" + i + ":" + e);
                    // fileContent += dateType+":" + i + ":\t" + e + tcont
                    // + "\r\n";
                }
            }
            mt.end();
            mt.disp();
            // if(mf.existsDictionary(strSaveDir + fileName)){
            // mf.createFile(strSaveDir + fileName, fileContent);
            // }

        }
        System.out.println("Get data end!");

        System.out.println("Server is running: " + jedis.ping());
    }

  通過管道進行批量操作:

private static void getDateByPipe() {
        Jedis jedis = new Jedis(rip, rport);
        jedis.auth(rpassword);
        System.out.println("Server is running: " + jedis.ping());
        // jedis.flushAll();
        MyTimeUtil mt = new MyTimeUtil();

        String strSaveDir = "d:\\edata\\";
        String fileName = "BAIHEYUAN_HW_"
                + new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date())
                + ".DJ";
        // String fileName="BAIHEYUAN_HW_20161122_0030.DJ";
        MyFileUtil mf = new MyFileUtil();
        String fileContent = null;
        Response<String> tcont = null;
        String dateType = "China_beijing_plane";
        System.out.println("Start to get data");
        for (int j = 0; j < 1; j++) {
            fileContent = null;

            mt.start();
            Pipeline pipeline = jedis.pipelined();

            for (int i = 0; i < 100; i++) {
                for (PlanProprity e : PlanProprity.values()) {
                    tcont = pipeline.get("China_beijing_plane:" + i + ":" + e);

                    fileContent += dateType + ":" + i + ":\t" + e + tcont
                            + "\r\n";
                }
            }
            pipeline.syncAndReturnAll();

            mt.end();
            mt.disp();

            if (mf.existsDictionary(strSaveDir + fileName)) {
                mf.createFile(strSaveDir + fileName, fileContent);
            }
        }
        System.out.println("Get data end!");
        System.out.println("Server is running: " + jedis.ping());
    }

  上面的代碼中除了獲取數據之外,另外還有一個導出數據到字符串和一個導出到文本的操作,後面發現這兩個操作大大影響了時間效率,因此作為對比,進行了註釋之後的二次測試.

  如果對於文件類比較感興趣可以參考下我寫的一個工具類: http://www.cnblogs.com/wangkun1993/p/7199326.html 自寫文件小工具類

  3.2.2.3 操作結果

  主獲取數據測試:
  單個獲取10000條數據時間:64704ms
    去掉寫數據操作 19356ms 20747ms 17678ms 20170ms
  單個獲取1000條數據時間:3202ms 2432ms 1791ms 2857ms 2218ms 2107ms
    去掉寫數據操作 1255ms 1267ms 1570ms 1408ms 1137ms
  單個獲取100條數據時間:186ms
    去掉寫數據操作 169ms 180ms 236ms 218ms
  批量獲取10000條數據時間:31367ms 31749ms 23582ms
    去掉寫數據操作 367ms 308ms 375ms
  批量獲取1000條數據時間:171ms 215ms 208ms 226ms 248ms 199ms 185ms 177ms
    去掉寫數據操作 86ms 62ms 45ms


  從獲取數據測試:
  單個獲取1000條數據時間:1675ms 826ms 691ms 667ms 1112ms 1930ms 614ms
    去掉寫數據操作 955ms 818ms 959ms 1007ms 1187ms 338ms 494ms
  單個獲取100條數據時間:66ms 44ms 46ms
    去掉寫數據操作 121ms 137ms 101ms
  批量個獲取10000條數據時間:29965ms 30986ms 22533ms
    去掉寫數據操作 363ms 323ms 360ms
  批量獲取1000條數據時間:174ms 145ms 135ms
    去掉寫數據操作 55ms 27ms 12ms

  3.2.2.4 結果分析

  從上面的數據可以看到,通過管道獲取數據想效率比一般獲取數據要高的多,因此數據量比較多的時候顯然管道操作是比較合適的,如果只是幾個數據的操作,一般兩種方式都行了.

  對於操作的時候如果進行一些文件的導出操作,可以看到完成的時間是大大增加了,因此如果需要在獲取數據之後進行一些其他的操作,最好認真斟酌一下,可以在數據獲取完畢之後直接從內存中讀取數據,進行一系列的操作.  

  3.2.3 恢復數據測試

   3.2.3.1 操作方法

  通過代碼,針對操作之後恢復數據的時間進行一個判斷,

  3.2.3.2 操作代碼

private static void testRecovery() {
        Jedis jedis = new Jedis(rip, rport);

        long t = 0;
        boolean tag=true;
        for (int i = 0; i < 1;) {
            try {
                

                String ttt = null;

                if ("OK" .equals(jedis.auth(rpassword))&&tag==true) {
                    t = System.currentTimeMillis();
                    System.out.println(System.currentTimeMillis() - t+" OK");//break;
                    tag=false;
                }
                if ("PONG".equals(jedis.ping())) {
                    System.out.println(System.currentTimeMillis() - t+" PONG");//break;
                }
                if (jedis.dbSize() >= 20000) {
                    System.out.println((System.currentTimeMillis() - t)+" all data");
                    break;
                }
            } catch (Exception e) {
                // TODO: handle exception
                System.out.println("test");
            }

        }
        System.out.println(System.currentTimeMillis() - t+" all out");
    }

  代碼沒有什麽特殊的地方,直接運行就行了,運行之後才打開redis進行恢復操作,從文件恢復的時間太短,不好統計,直接取的它自己顯示的數字,主要測試的是遠程服務器傳輸數據需要話費的時間.

  3.2.3.3 操作結果

  主恢復數據測試(2w數據880kb)
    直接dump文件恢復(s) 0.044 0.049 0.047
    測試20w(2.89m)恢復時間) 0.15s
    刪除主機備份文件無法恢復.
  從恢復數據測試(2w數據880kb)
    直接dump文件恢復(s) 0.40 0.039 0.040 0.039
    刪除從機備份文件之後網絡獲取文件回復
    2w數據3.35s 3.40s

  3.2.3.4 結果分析

  從結果來看,影響恢復速度的因素主要是網絡的問題,從文件恢復幾乎可以在秒級完成,可以忽略不計,當然需要看情況啦,至少我邊項目不需要考慮從文件恢復的時間.恢復的速度還是比較滿意的,測試數據時候的因為是內部網絡,所以這個值不好做評判參考類.

  目前測試就這些,後續可能繼續進行其他測試,會繼續修改這個博客.

  個人原創,轉載請註明出處.

  歡迎指出不足之處以作改進.

  

redis性能測試