Redis Pipeline詳解

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();
	}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章