17-SpringBoot之Redis(四)——Redis流水線
阿新 • • 發佈:2018-11-28
SpringBoot之Redis(四)——Redis流水線
在預設的情況下, Redis 客戶端是一條條命令傳送給Redis 伺服器的,這樣顯然效能不高。在關係資料庫中我們可以使用批量,也就是隻有需要執行SQL 時,才一次性地傳送所有的SQL 去執行,這樣效能就提高了許多。對於Redis 也是可以的,這便是流水線( pipline )技術,在很多情況下並不是Redis 效能不佳,而是網路傳輸的速度造成瓶頸,使用流水線後就可以大幅度地在需要執行很多命令時提升Redis 的效能。
為測試流水線效能,分別使用單條插入的方式和Redis流水線技術測試100 萬次讀寫的功能實驗,單條插入方式的實現程式碼如下:
@RequestMapping("/testSingle")
public Map<String, Object> testSingle() {
Long start = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
String key = "pipeline_" + i;
String value = "value_" + i;
redisTemplate.opsForValue().set (key, value);
}
Long end = System.currentTimeMillis();
System.out.println("Single插入1000000條記錄耗時:" + (end - start) + "毫秒。");
Map<String, Object> map = new HashMap<String, Object>();
map.put("success", true);
return map;
}
使用redis流水線技術實現程式碼如下:
@RequestMapping("/testPipeline")
public Map<String, Object> testPipeline() {
Long start = System.currentTimeMillis();
List List = redisTemplate.executePipelined(new RedisCallback<Long>() {
@Nullable
@Override
public Long doInRedis(RedisConnection connection) throws DataAccessException {
connection.openPipeline();
for (int i = 1000001; i < 2000000; i++) {
String key = "pipeline_" + i;
String value = "value_" + i;
connection.set(key.getBytes(), value.getBytes());
}
return null;
}
});
Long end = System.currentTimeMillis();
System.out.println("Pipeline插入1000000條記錄耗時:" + (end - start) + "毫秒。");
Map<String, Object> map = new HashMap<String, Object>();
map.put("success", true);
return map;
}
分別呼叫這兩個方法。控制檯記錄的執行時間:
從實驗結果可以看出,使用redis流水線插入可以大幅度提高效能,它十分適合大資料量的執行。
這裡需要注意的是以下兩點。
- 在執行如此多的命令時,需要考慮的另外一個問題是記憶體空間的消耗,因為對於程式而言,它最終會返回一個List 物件,如果過多的命令執行返回的結果都儲存到這個List中,顯然會造成記憶體消耗過大,尤其在那些高併發的網站中就很容易造成JVM記憶體溢位的異常, 這個時候應該考慮使用迭代的方法執行Redis命令。
- 與事務一樣,使用流水線的過程中, 所有的命令也只是進入佇列而沒有執行,所以執行的命令返回值也為空,這也是需要注意的地方。