1、pipeline出現的背景:
redis客戶端執行一條命令分4個過程:
發送命令-〉命令排隊-〉命令執行-〉返回結果
這個過程稱爲Round trip time(簡稱RTT, 往返時間),mget mset有效節約了RTT,但大部分命令(如hgetall,並沒有mhgetall)不支持批量操作,需要消耗N次RTT ,這個時候需要pipeline來解決這個問題。
二、pepeline的性能
1、未使用pipeline執行N條命令
2、使用了pipeline執行N條命令
3、兩者性能對比
小結:這是一組統計數據出來的數據,使用Pipeline執行速度比逐條執行要快,特別是客戶端與服務端的網絡延遲越大,性能體能越明顯。
下面貼出測試代碼分析兩者的性能差異:
@Test
public void pipeCompare() {
Jedis redis = new Jedis("192.168.1.111", 6379);
redis.auth("12345678");//授權密碼 對應redis.conf的requirepass密碼
Map<String, String> data = new HashMap<String, String>();
redis.select(8);//使用第8個庫
redis.flushDB();//清空第8個庫所有數據
// hmset
long start = System.currentTimeMillis();
// 直接hmset
for (int i = 0; i < 10000; i++) {
data.clear(); //清空map
data.put("k_" + i, "v_" + i);
redis.hmset("key_" + i, data); //循環執行10000條數據插入redis
}
long end = System.currentTimeMillis();
System.out.println(" 共插入:[" + redis.dbSize() + "]條 .. ");
System.out.println("1,未使用PIPE批量設值耗時" + (end - start) / 1000 + "秒..");
redis.select(8);
redis.flushDB();
// 使用pipeline hmset
Pipeline pipe = redis.pipelined();
start = System.currentTimeMillis();
//
for (int i = 0; i < 10000; i++) {
data.clear();
data.put("k_" + i, "v_" + i);
pipe.hmset("key_" + i, data); //將值封裝到PIPE對象,此時並未執行,還停留在客戶端
}
pipe.sync(); //將封裝後的PIPE一次性發給redis
end = System.currentTimeMillis();
System.out.println(" PIPE共插入:[" + redis.dbSize() + "]條 .. ");
System.out.println("2,使用PIPE批量設值耗時" + (end - start) / 1000 + "秒 ..");
//--------------------------------------------------------------------------------------------------
// hmget
Set<String> keys = redis.keys("key_*"); //將上面設值所有結果鍵查詢出來
// 直接使用Jedis hgetall
start = System.currentTimeMillis();
Map<String, Map<String, String>> result = new HashMap<String, Map<String, String>>();
for (String key : keys) {
//此處keys根據以上的設值結果,共有10000個,循環10000次
result.put(key, redis.hgetAll(key)); //使用redis對象根據鍵值去取值,將結果放入result對象
}
end = System.currentTimeMillis();
System.out.println(" 共取值:[" + redis.dbSize() + "]條 .. ");
System.out.println("3,未使用PIPE批量取值耗時 " + (end - start) / 1000 + "秒 ..");
// 使用pipeline hgetall
result.clear();
start = System.currentTimeMillis();
for (String key : keys) {
pipe.hgetAll(key); //使用PIPE封裝需要取值的key,此時還停留在客戶端,並未真正執行查詢請求
}
pipe.sync(); //提交到redis進行查詢
end = System.currentTimeMillis();
System.out.println(" PIPE共取值:[" + redis.dbSize() + "]條 .. ");
System.out.println("4,使用PIPE批量取值耗時" + (end - start) / 1000 + "秒 ..");
redis.disconnect();
}