Redis性能調優(yōu)办龄,影響Redis性能的因素

序言

上一篇文章《Redis為什么這么快》介紹了Redis性能評估工具姻乓,以及Redis高性能的原因猪瞬。詳細請見: 這篇我們將從業(yè)務的視角啸胧,講解下影響Redis性能的因素以及如何提升Redis使用的性能邑闲。

從用戶到Redis請求過程分析

以最常用場景緩存為例戳寸,流量從用戶到Redis Server的過程如下所示:

image

image

  1. 用戶訪問后端服務器兜畸,調用對應的Controller

  2. Controller命中緩存記錄努释,通過Jedis客戶端調用Reids從緩存獲取記錄。 如果使用的Jedis連接池獲取Jedis對象咬摇,從Jedis連接池獲取一個Jedis連接實例伐蒂。

  3. Jedis使用Redis序列化協議(RESP)將命令編碼,放到Redis Server輸入緩沖區(qū)中肛鹏。

  4. Redis Server從輸入緩沖區(qū)獲取命令并執(zhí)行逸邦。

  5. 執(zhí)行結束后將執(zhí)行結果放入到輸出緩沖區(qū)。

  6. Jedis客戶端從輸出緩沖區(qū)獲取執(zhí)行結果并返回給Controller在扰。

  7. Controller執(zhí)行完業(yè)務邏輯相應用戶的請求缕减。

從上面時序圖可以看出,用戶請求通過Redis client經由網路到達Redis Server芒珠。

因此在考慮使用Redis性能的時候要從客戶端和服務端兩個角度考慮桥狡。 對于業(yè)務方來說, 合理使用Redis特性比Redis服務器的優(yōu)化可操作性更強皱卓,也更容易獲得好的效果裹芝。

下面將從業(yè)務優(yōu)化和服務器優(yōu)化兩個方面介紹Redis的優(yōu)化。

業(yè)務優(yōu)化

查詢本地redis的延遲通常低于1毫秒娜汁,而查詢同一個數據中心的redis的延遲通常低于5毫秒嫂易。也就是說,網絡傳輸的損耗為實際操作用時的5倍掐禁。

因此怜械,從客戶端角度颅和,如何減少網絡耗時至關重要。

使用連接池減少建立連接和銷毀連接的時間開銷

Jedis是Java語言使用最多的Redis客戶端缕允。 Jedis支持直連和連接池的兩種方式融虽。

直連的方式:

# 1. 生成一個Jedis對象,這個對象負責和指定Redis實例進行通信 Jedis jedis = new Jedis("127.0.0.1", 6379); # 2. jedis執(zhí)行set操作 jedis.set("hello", "world"); # 3. jedis執(zhí)行get操作 value="world" String value = jedis.get("hello");

所謂直連是指Jedis每次都會新建TCP 連接灼芭,使用后再斷開連接。 我們都知道新建TCP連接經過3次握手般又,釋放TCP連接經過4次揮手彼绷,新建和回收是非常耗時操作。對于頻繁訪問Redis的場景顯然不是高效的使用方式茴迁。

Jedis也提供了連接池的方式寄悯。
節(jié)選自:《Redis開發(fā)和運維》

節(jié)選自:《Redis開發(fā)和運維》

// common-pool連接池配置,這里使用默認配置GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); // 初始化Jedis連接池 JedisPool jedisPool = new JedisPool(poolConfig, "127.0.0.1", 6379);Jedis jedis = null; try {  // 1. 從連接池獲取jedis對象   jedis = jedisPool.getResource();   // 2. 執(zhí)行操作   jedis.get("hello"); } catch (Exception e) {     logger.error(e.getMessage(),e); } finally {   if (jedis != null) {   // 如果使用JedisPool堕义,close操作不是關閉連接猜旬,代表歸還連接池   jedis.close();   } }

使用Pipeline或者Lua腳本減少請求次數

通過連接池,減少建立和斷開TCP連接的時間開銷倦卖。 另外洒擦,redis提供了其他三種方式,通過減少請求次數提升性能怕膛。 (1) 批量操作的命令熟嫩,如mget,mset等 (2) pipeline方式 (3) Lua腳本

pipeline方式

使用redis-benchmark在Intel(R) Xeon(R) CPU E5520 @ 2.27GHz對比pipeline(每次16個命令)和普通請求褐捻。

使用pipeline的情況:

$ ./redis-benchmark -r 1000000 -n 2000000 -t get,set,lpush,lpop -P 16 -qSET: 552028.75 requests per secondGET: 707463.75 requests per secondLPUSH: 767459.75 requests per secondLPOP: 770119.38 requests per secondIntel(R) Xeon(R) CPU E5520 @ 2.27GHz (without pipelining)

無pipeline的情況:

$ ./redis-benchmark -r 1000000 -n 2000000 -t get,set,lpush,lpop -qSET: 122556.53 requests per secondGET: 123601.76 requests per secondLPUSH: 136752.14 requests per secondLPOP: 132424.03 requests per second

從benchmark的結果可以看出掸茅,使用pipeline技術比沒有使用性能提升5-10倍左右。

Jedis支持Pipeline特性柠逞,我們知道 Redis提供了mget昧狮、mset方法,但是并沒有提供mdel方法板壮,如果想實現這個功 能逗鸣,可以借助Pipeline來模擬批量刪除,雖然不會像mget和mset那樣是一個原 子命令个束,但是在絕大數場景下可以使用慕购。

public void mdel(List<String> keys) {   Jedis jedis = new Jedis("127.0.0.1");   // 1)生成pipeline對象 Pipe     line pipeline = jedis.pipelined();   // 2)pipeline執(zhí)行命令,注意此時命令并未真正執(zhí)行   for (String key : keys) {       pipeline.del(key);  }  // 3)執(zhí)行命令   pipeline.sync(); }

將del命令封裝到pipeline中茬底,可以調用pipeline.del(String key)沪悲,此時不會真正的 執(zhí)行命令。

使用pipeline.sync()完成此次pipeline對象的調用阱表。

除了pipeline.sync()殿如,還可以使用pipeline.syncAndReturnAll()將 pipeline的命令進行返回贡珊。

pipeline提升性能的原因

pipeline提升性能的一個原因是減少了命令總的RTT時間(往返時延), 另外一方面減少 總的系統(tǒng)調用的次數。

RTT(Round-Trip Time): 往返時延涉馁。在計算機網絡中它是一個重要的性能指標门岔,表示從發(fā)送端發(fā)送數據開始,到發(fā)送端收到來自接收端的確認(接收端收到數據后便立即發(fā)送確認)烤送,總共經歷的時延寒随。往返延時(RTT)由三個部分決定:即鏈路的傳播時間、末端系統(tǒng)的處理時間以及路由器的緩存中的排隊和處理時間帮坚。其中妻往,前面兩個部分的值作為一個TCP連接相對固定,路由器的緩存中的排隊和處理時間會隨著整個網絡擁塞程度的變化而變化试和。所以RTT的變化在一定程度上反映了網絡擁塞程度的變化讯泣。簡單來說就是發(fā)送方從發(fā)送數據開始,到收到來自接受方的確認信息所經歷的時間阅悍。

pipline和lua腳本的不同

Redis原生支持Lua語言好渠,并且提供了通過客戶端執(zhí)行l(wèi)ua腳本的命令。

Redis Lua腳本相關命令腦圖

Redis Lua腳本相關命令腦圖

比如我們可以用Lua腳本在低版本的Redis上實現分布式鎖节视。

local current current = redis.call('incr',KEYS[1]) if tonumber(current) == 1 then redis.call('expire',KEYS[1], ARGV[1]) end return current

調用EVAL命令可以傳入不定的KEY和ARGS的值拳锚, 這些值被可以通過KEY[i]和ARGV[i]訪問對應的入參,并且通過return返回執(zhí)行結果肴茄。

更多的Lua腳本晌畅,會在其他文章中介紹。

可以關注微信公眾號:非典型理科男寡痰,查看全部文章列表閱讀Lua腳本相關的文章抗楔。

pipeline和Lua比較:

(1) 返回結果不同: pipeline會把命令執(zhí)行結果都返回出來, lua腳本只有一個返回結果拦坠。

(2) 使用場景不同: lua腳本可以提供復雜邏輯運算并且提供了緩存腳本的功能连躏,提升像原生命令一樣的性能體驗。 因此lua腳本可以用在處理邏輯復雜贞滨,不需要返回或者只返回操作結果的場景入热。 pipeline用在合并命令減少執(zhí)行開銷和redis server壓力的場景下。

在使用pipeline時有幾個注意事項:

(1) pipeline執(zhí)行命令雖然沒有明確的執(zhí)行命令數量的限制晓铆,但是建議限制執(zhí)行命令數量勺良。 執(zhí)行命令數量過多一方面占用網絡帶寬,另一方面會阻塞客戶端骄噪。

Redis Server性能影響因素

影響Redis Server性能主要有硬件尚困、數據分布和配置有關。

硬件因素

Redis喜歡下面的硬件條件:

  1. 高帶寬链蕊,低延遲的網絡: Redis的性能中網絡帶寬和延遲通常是最大短板事甜。因此谬泌,需要選擇高帶寬,低延遲的網絡逻谦。

  2. 大緩存快速 CPU: 而不是多核掌实。這種場景下面,比較推薦 Intel CPU邦马。AMD CPU 可能只有 Intel CPU 的一半性能(通過對 Nehalem EP/Westmere EP/Sandy 平臺的對比)贱鼻。 當其他條件相當時候,CPU 就成了 redis-benchmark 的限制因素滋将。

  3. 大對象(>10k)存儲時內存和帶寬顯得尤其重要忱嘹。 但是更重要是優(yōu)化大對象的存儲。

  4. 將Redis運行在物理機器上:Redis 在 VM 上會變慢耕渴。虛擬化對普通操作會有額外的消耗,Redis 對系統(tǒng)調用和網絡終端不會有太多的 overhead齿兔。建議把 Redis 運行在物理機器上橱脸。

大Value的影響

包大小影響Redis的相應速度。 以太網網數據包在 1500 bytes 以下時分苇, 將多條命令包裝成 pipelining 可以大大提高效率添诉。事實上,處理 10 bytes医寿,100 bytes栏赴, 1000 bytes 的請求時候,吞吐量是差不多的靖秩,詳細可以見下圖须眷。

不同數據包大小下的并發(fā)量

不同數據包大小下的并發(fā)量

所以,當大value(>10k)存在時要及時優(yōu)化掉沟突。

參考文檔:

  1. Redis Benchmark

  2. Redis 命令合集

什么是架構設計花颗?架構設計看這篇文章就夠了

Redis為什么這么快?

重磅:解讀2020年最新JVM生態(tài)報告

BIO,NIO,AIO 總結

JDK8的新特性惠拭,你知道多少扩劝?

回復“資料”,免費獲取 一份獨家嘔心整理的技術資料职辅!
image
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末棒呛,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子域携,更是在濱河造成了極大的恐慌簇秒,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件涵亏,死亡現場離奇詭異宰睡,居然都是意外死亡蒲凶,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門拆内,熙熙樓的掌柜王于貴愁眉苦臉地迎上來旋圆,“玉大人,你說我怎么就攤上這事麸恍×榍桑” “怎么了?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵抹沪,是天一觀的道長刻肄。 經常有香客問我,道長融欧,這世上最難降的妖魔是什么敏弃? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮噪馏,結果婚禮上麦到,老公的妹妹穿的比我還像新娘。我一直安慰自己欠肾,他們只是感情好瓶颠,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著刺桃,像睡著了一般粹淋。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上瑟慈,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天桃移,我揣著相機與錄音,去河邊找鬼葛碧。 笑死谴轮,一個胖子當著我的面吹牛,可吹牛的內容都是我干的吹埠。 我是一名探鬼主播第步,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼缘琅!你這毒婦竟也來了粘都?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤刷袍,失蹤者是張志新(化名)和其女友劉穎翩隧,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體呻纹,經...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡堆生,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年专缠,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片淑仆。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡涝婉,死狀恐怖,靈堂內的尸體忽然破棺而出蔗怠,到底是詐尸還是另有隱情墩弯,我是刑警寧澤,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布寞射,位于F島的核電站渔工,受9級特大地震影響,放射性物質發(fā)生泄漏桥温。R本人自食惡果不足惜引矩,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望侵浸。 院中可真熱鬧脓魏,春花似錦、人聲如沸通惫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽履腋。三九已至,卻和暖如春惭嚣,著一層夾襖步出監(jiān)牢的瞬間遵湖,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工晚吞, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留延旧,地道東北人。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓槽地,卻偏偏與公主長得像迁沫,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子捌蚊,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內容

  • Java客戶端Jedis Java有很多優(yōu)秀的Redis客戶端(詳見:http://redis.io/client...
    linuxzw閱讀 1,508評論 1 5
  • NOSQL類型簡介鍵值對:會使用到一個哈希表缅糟,表中有一個特定的鍵和一個指針指向特定的數據挺智,如redis,volde...
    MicoCube閱讀 3,985評論 2 27
  • 在之前的文章中窗宦,我們對redis批量處理指令mget進行了壓測并分析了性能瓶頸赦颇,顯然通過mget批量執(zhí)行指令可以節(jié)...
    近路閱讀 39,275評論 4 18
  • 1 Redis介紹1.1 什么是NoSql為了解決高并發(fā)订讼、高可擴展、高可用沪摄、大數據存儲問題而產生的數據庫解決方...
    克魯德李閱讀 5,296評論 0 36
  • 我是個悲觀主義者躯嫉,悲觀就是清醒,就是看得通透杨拐,所以不會因為眼前的事產生困頓感祈餐。你得清楚意識到,人生整體就是結束哄陶,就...
    Sunny飛鏡閱讀 124評論 0 0