redis pipeline
什么是流水線(pipeline)
首先來看 redis 執行一次操作所需要的時間:
1 次時間 = 1 次網絡時間 + 1次命令時間
執行 n 次就需要:
n 次時間 = n 次網絡時間 + n 次命令時間
所以可以看到,如果執行 n 次的話(比如 n 次 set 操作),時間開銷是非常大的。
由於命令時間非常短,影響時間開銷的主要是網絡時間,所以我們可以把一組命令打包,然后一次發送過去。這樣的話,時間開銷就變為:
1 次 pipeline(n條命令) = 1 次網絡時間 + n 次命令時間
pipeline 的好處
- 省略由於單線程導致的命令排隊時間,一次命令的消耗時間=一次網絡時間 + 命令執行時間
- 比起命令執行時間,網絡時間很可能成為系統的瓶頸
- pipeline的作用是將一批命令進行打包,然后發送給服務器,服務器執行完按順序打包返回。
- 通過pipeline,一次pipeline(n條命令)=一次網絡時間 + n次命令時間
命令 | N個命令操作 | 1次pipeline(n個命令) |
---|---|---|
時間 | n次網絡+n次命令 | 1次網絡+n次命令 |
數據量 | 1條命令 | n條命令 |
pipeline VS M 操作(mget、mset)
之前我們講過 M 操作,也是類似 pipeline,將多個命令一次執行,一次發送出去,節省網絡時間。對比如下:
- M操作在Redis隊列中是一個原子操作,pipeline不是原子操作
- pipeline與M操作都會將數據順序的傳送順序地返回(redis 單線程)
- M 操作一個命令對應多個鍵值對,而Pipeline是多條命令
pipeline注意事項
- 每次pipeline攜帶數量不推薦過大,否則會影響網絡性能
- pipeline每次只能作用在一個Redis節點上
pipeline-Jedis使用
Maven 依賴
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
代碼如下
//沒有使用pipieline的情況下
public void testWithoutPipeline() {
Jedis jedis = new Jedis("127.0.0.1" , 6379);
for(int i = 1 ; i <= 10000 ; i++ ) {
jedis.hset("hashKey-" + i , "field-" + i , "value-" + i);
}
}
//使用pipeline的情況下
public void testPipeline() {
Jedis jedis = new Jedis("127.0.0.1" , 6379);
for(int i = 0 ; i < 100 ; i++ ) {
Pipeline pipeline = jedis.pipelined();
for(int j = i * 100 ; i < (i+1) * 100 ; j++ ) {
pipeline.hset("hashKey-" + j , "field-" + j , "value-" + j);
}
pipeline.syncAndReturnAll();
}
}