為什么使用 Pipeline?
Redis客戶端執行一條命令分為如下四個過程:
- 發送命令
- 命令排隊
- 命令執行
- 返回結果
其中,1到4稱為Round Trip Time(RTT,往返時間)。
Redis提供了批量操作命令(例如mset、mget等),有效地節省了RTT。但大部分命令是不支持批量操作的,例如要執行n次hgetall命令,並沒有mhgetall命令存在,需要消耗n次RTT。Redis的客戶端和服務端可能部署在不同的機器上。例如客戶端在北京,Redis服務器在上海,兩地直線距離1300公里,那么一次RTT時間= 1300 x2 / 3000000 x
2/3) = 13毫秒(光在真空中的傳輸速度為30萬公里/秒,這里假設光纖為光速的2/3),那么客戶端在1秒內大約只能執行80次左右的命令,這個Redis的高並發高吞吐特性背道而馳。
總結:Redis的pipeline功能的原理是 客戶端通過一次性將多條redis命令發往Redis 服務端,減少了每條命令分別傳輸的IO開銷。同時減少了系統調用的次數,因此提升了整體的吞吐能力。
未使用pipeline執行N條命令
使用了pipeline執行N條命令
go語言下Pipeline使用
- 獲取Redis對象(一般從連接池中獲取)
- 獲取Redis對象的pipeline對象
- 添加指令
- 執行指令
package main import ( "github.com/go-redis/redis" "log" "strconv" ) func main() { client := redis.NewClient(&redis.Options{ Addr: "localhost:6379", Password: "", // no password set DB: 0, // use default DB Network: "tcp", PoolSize: 50, }) if _, err := client.Ping().Result(); err != nil { panic(err) } pipe := client.Pipeline() pipe.Get("key1") pipe.Get("key2") pipe.Get("key3") result, err := pipe.Exec() defer client.Close() }
redis-go:
github:https://github.com/alphazero/Go-Redis
原生批量命令(mset, mget)與Pipeline對比
可以使用Pipeline模擬出批量操作的效果,但是在使用時要注意它與原生批量命令的區別,主要包括如下幾點:
- 原生批量命令是原子的,Pipeline是非原子的;
- 原生批量命令是一個命令對應多個key,Pipeline支持多個命令;
- 原生批量命令是Redis服務端支持實現的,而Pipeline需要服務端和客戶端的共同配合。
參考:
https://blog.csdn.net/w1lgy/article/details/84455579?utm_medium=distribute.wap_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.wap_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase