一次Redis client组件性能分析
??????? BeetleX也擴(kuò)展了RedisClient驅(qū)動,寫這些高并發(fā)應(yīng)用的驅(qū)動性能測試分析是必不可少的。在最近一次測試中發(fā)現(xiàn)測試采樣度不足,引起的一些問題;通過這一次的問題也警醒一下自己在以后設(shè)計上要考慮更多細(xì)節(jié)的特性需求。
發(fā)現(xiàn)問題
????????在寫組件的時候往往會拿同樣的組件產(chǎn)品做一些簡單的測試性能對象,最近也拿BeetleX.Redis組件和其他組件做了一下性能測試,經(jīng)過兩次測試環(huán)境的采樣發(fā)現(xiàn)的結(jié)果差異還是很大的,如下是兩個環(huán)境的測試結(jié)果:
4核環(huán)境
20核環(huán)境
從兩個測試環(huán)境的結(jié)果來看StackExchange.Redis由原來并發(fā)數(shù)量最差,到后面領(lǐng)先了50%。
問題所在
????????這問題分析很久,包括用Redis-cli來測發(fā)現(xiàn)該實例的Redis極限只能達(dá)到10RPS,但測試結(jié)果來看StackExchange.Redis已遠(yuǎn)超過Redis自身的交互吞吐量了。經(jīng)過查看代碼和相關(guān)文檔才發(fā)現(xiàn)StackExchange.Redis的async默認(rèn)即支持Redis的pipeline特性,并完美支持多線程環(huán)境操作。
????????以代碼上來看StackExchange.Redis為了讓組件默認(rèn)支持這特性讓Redis吞吐量最大化,所以在設(shè)計上也變得非常復(fù)雜和更多異步切換處理;這樣引起了代碼處理量比較多性能有些損耗。所以在StackExchange.Redis在配置低的情況達(dá)不到Redis滿負(fù)載時浪費(fèi)比較多的CPU資源性能相對就變得差了。
????????當(dāng)StackExchange.Redis運(yùn)行在資源比較多的服務(wù)器上時,高壓下輕易壓爆了Redis的交互IO量時那pipeline特性就可以在IO量不變的情況下更一步提高吞吐量。這是沒有默認(rèn)實現(xiàn)pipeline的組件所能比的。
總結(jié)
????????在這里不得不佩服StackExchange.Redis設(shè)計者的思路,在Client資源充足的情況把Redis的吞吐最大化發(fā)揮到極致。當(dāng)然這種設(shè)計也是針對性的,他是利用Redis的特性和大量的CPU來提高Redis的吞量能力。對于沒有默認(rèn)支持pipeline只能跑到Redis交互的上限,受Redis的限制對應(yīng)Client所使用的CPU自然也就無法上去來提高吞吐。
??????? StackExchange.Redis在20線程下可以跑到30%的CPU,其他則只能跑到15%. StackExchange.Redis的這種設(shè)計缺點就是Client資源比較低的情況下性能就相對來說差一些。
????????所以性能好壞還真的很難通過一些簡單的采樣就能得出個合理的結(jié)果,關(guān)注性能更多應(yīng)該關(guān)注代碼是否能更好地發(fā)揮相關(guān)資源的作用。很多時候測試方式都受制定者的主觀因素影響。如果沒有這次測試我還真自認(rèn)為BeetleX.Redis設(shè)計很不錯。
StackExchange.Redis超時問題
????????用過StackExchange.Redis的朋友相信一定碰到Timeout的問題...,其實這個和StackExchange.Redis設(shè)計有些關(guān)系,最直接的辦法是加大線程池和超時時間配置。對于CPU硬件資源少的還是加大超時時間比較好。主要原因是pipeline方式下意味著同時多個指令處理,但當(dāng)前會話awaiter receive線程就一個最后會觸發(fā)多個響應(yīng),如果響應(yīng)的消息后面有邏輯處理那自然會影響后面消息處理。
void IResultBox.ActivateContinuations() {if ((Task.CreationOptions & TaskCreationOptions.RunContinuationsAsynchronously) == 0)ThreadPool.UnsafeQueueUserWorkItem(s_ActivateContinuations, this);elseActivateContinuationsImpl(); }從最終代碼來看,ActivateContinuationsImpl則由當(dāng)前awaiter receive線程觸發(fā),串行得太多后面的消息處理不及時就會引起超時。
ConnectionMultiplexer會每秒探測還在隊列中等待響應(yīng)的命令,如果有超時直接就觸發(fā)對應(yīng)命令的timeout(由于全局性的pipeline處理非常復(fù)雜也有可能 是處理過程存在一些問題,可以嘗試用同步指令,從測試結(jié)果來看同步指令沒用pipeline).
總結(jié)
以上是生活随笔為你收集整理的一次Redis client组件性能分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Async和Await异步编程的原理
- 下一篇: 乐观锁与悲观锁各自适用场景是什么?