轉:https://www.jianshu.com/p/172b39244c85
MGET
是redis中較為常用的命令,用來批量獲取給定key對應的value。因為redis使用基於RESP (REdis Serialization Protocol)協議的rpc接口,而redis本身的數據結構非常高效,因此在日常使用中,IO和協議解析是個不容忽略的資源消耗。通過mget將多個get請求匯聚成一條命令,可以大大降低網絡、rpc協議解析的開銷,從而大幅提升緩存效率。mget
的定義如下(來自REDIS命令參考):
MGET key [key ...]
返回所有(一個或多個)給定 key 的值。 如果給定的 key 里面,有某個 key 不存在,那么這個 key 返回特殊值 nil 。因此,該命令永不失敗。 返回值: 一個包含所有給定 key 的值的列表。q 例: redis> SET redis redis.com OK redis> SET mongodb mongodb.org OK redis> MGET redis mongodb 1) "redis.com" 2) "mongodb.org"
但是,在某些需要一次批量查詢大量key的場景下,我們會發現mget
並沒有想象中的那么完美。
以電商庫存系統(或價格系統)為例,作為原子級的服務,我們經常要面對商品列表頁、活動頁、購物車、交易等系統的批量查詢,一次請求中動輒包含幾十甚至上百個sku,此時mget
是否還能像我們想象中那般保持極高的吞吐?
我們先來設計一個實驗,探一探mget
性能的底。
1 實驗設計
在本地進行了壓測模擬,redis key設計:
- key為string類型,固定為八位數字字符串以模擬SKU ID,不足8位者高位填0
- value為5位整型數字,模擬商品庫存
- 實驗中將SKU ID設置為1~500000的數字
單元測試代碼設計原則:
- 可以方便地調整測試參數
- 盡量減少GC對結果的影響,設置合適的堆空間和垃圾回收器
壓測代碼做了局部優化以盡量保證結果的准確性,包括:
- 針對每一輪壓測,提前准備好隨機的key列表,避免隨機生成key列表時大量的內存操作對測試結果造成影響
- 每一輪壓測統計多次mget的平均執行時間
- 每一輪壓測完成后,強制觸發fullgc,盡量避免在壓測進行中發生gc