1

我有一個在AWS ECS的linux容器中運行的ASP.Net Core Web API。此API主要從Redis獲取數據,但如果數據庫不在那裏(我們設計了99.99%的數據位於Redis緩存中),它們將回退到數據庫。我有一個相當高的負載進來約1-2K RPS(當然也許中到小到一些;-)。使用Stackexchange,負載下的MGET調用變得越來越慢。Redis

該API通過MGET(每個20-60的任何位置)查找幾個密鑰,以查找每個請求。一切都是異步的,沒有同步代碼或等待或其他死鎖代碼。 RPS越高,事情越慢,速度越慢。我也嘗試過PreserveAsyncOrder = false,但那似乎更糟。

我不認爲我的Redis服務器(在Elasticache中)是問題,指標顯示CPU利用率幾乎不到1%。另外,我創建的容器實例越多,延遲時間越長,我不希望看到服務器是否是瓶頸。

我聽說TPL和SE.Redis有一個潛在的線程劫持問題(不知道它是否修復或者適用於.Net Core),所以我試着將所有東西都移動到同步而不是異步(雖然我的網絡API調用仍然是異步的,但我對SE.Redis的調用是同步的)。這導致實際的超時而不是僅僅花費一段時間:

超時執行MGET,inst:5,隊列:199,qu:0,qs:199,qc:0,wr:0,wq:0,in:150304 ,ar:0,客戶端名稱:,serverEndpoint:10.55.148.227:6379,keyHashSlot:-2

因爲這是.Net Core超時異常似乎給予較少的信息比完整的堆棧,我看不到數量工作者線程或IOCP線程來查看是否存在瓶頸。

隨着越來越多的超時發生,queue/qs:number和in:number一樣增加。

這個數字讓我相信我得到的迴應只是沒有足夠快地處理它,我是否會陷入線程劫持問題?或者,也許我的客戶端是網絡綁定?

我也嘗試爲redis連接創建連接池,如SE.Redis超時頁面所示。非常小的改進,但仍面臨同樣的問題。

任何幫助,將不勝感激。

回答

-1

Redis是單線程的。你正在增加單線程的負載,所以它的響應速度慢是有道理的。 MGET在單個批處理中只是多次GET操作,所以如果您爲每個請求執行20-60 GET並且每秒執行2k個請求,那麼Redis每秒處理大約30-120k操作。

要麼達到雲虛擬機CPU或網絡飽和的最大吞吐量。

嘗試使用隨機密鑰進行一些負載測試以首先查找最大容量,以便知道是否足以滿足您的應用程序,然後您可以對其進行建模。

您可以使用散列將類似數據組合成單個鍵或使用更多服務器(或更多CPU上的實例)進行分片。 Redis集羣執行自動分片。

+0

我相信這不是問題。 1.在上面的原始問題中,我提到Redis服務器似乎幾乎沒有出汗。事實上,如果我從不同的機器連接,一切仍然很快。 2.您可以看到有一個未處理的本地隊列。這與服務器無關。 3。我寫了我自己的圖書館,因爲這似乎沒有得到解決,也沒有受到這個問題的困擾。 – Cleverguy25