關鍵詞:Redis數據庫延遲響應延遲
本文將幫助您找出Redis響應延遲的問題。
本文中的延遲是指從客戶端發出命令到客戶端收到命令反饋的最長響應時間。Reids的處理時間通常很慢,大概在亞細微範圍,但也有更長的情況。
計算延遲時間
如果妳正在經歷響應延遲,妳或許可以根據應用的具體情況計算出它的延遲響應時間,或者妳的延遲問題非常明顯,從宏觀角度來看,壹目了然。無論如何,使用redis-cli,您可以計算redis服務器延遲了多少毫秒。踢這句話:
redis-CLI-latency-h ` host `- p ` port '
網絡和通信造成的延遲
當用戶通過TCP/IP連接或Unix域連接連接Redis時,千兆網絡的典型延遲約為200us,而Unix域socket可能低至30us。這完全取決於您的網絡和系統硬件。在通信本身之上,系統增加了更多的延遲(線程調度、CPU緩存、NUMA替換等。).在虛擬機環境中,系統造成的延遲比在物理機環境中高得多。
現實情況是,即使Redis以微秒處理大多數命令,客戶機和服務器之間的交互也不可避免地會消耗系統相關的延遲。因此,高效的客戶端試圖通過將多個命令捆綁在壹起來減少交互的數量。服務器和大多數客戶端都支持這種方法。像MSET/MGET這樣的聚合命令也可以用於此目的。從Redis 2.4版開始,許多命令也支持所有數據類型的可變參數。
以下是壹些指導原則:
如果可以的話,盡量使用物理機而不是虛擬機作為服務器。
不要頻繁連接/斷開與服務器的連接(尤其是基於web的應用),盡可能延長與服務器的連接時間。
如果您的客戶端和服務器在同壹臺主機上,請使用Unix域套接字。
盡量使用集合命令(MSET/MGET)或可變參數命令,而不是流水線。
如果可以嘗試用流水線代替串行往返命令。
對於原來的流水線不適合的情況,比如壹個命令的結果是後續命令的輸入,在後來的版本中,redis在服務器端提供了對lua腳本的支持,現在可以使用實驗分支版本。
在Linux上,可以通過進程放置(taskset)、cgroups、實時優先級(chrt)、NUMA配置(numactl)或者使用低延遲內核來獲得更低的延遲。請註意,Redis不適合綁定到單個CPU內核。Redis會在後臺創建壹些消耗CPU的進程,比如bgsave和AOF重寫。這些任務不能與主事件循環進程放在同壹個CPU內核上。大多數情況下,以上優化方法都是不必要的,除非妳真的需要,而且妳很熟悉。
Redis的單線程特性
Redis使用單線程設計,這意味著單線程服務於所有客戶端請求,並使用重用技術。在這種情況下,redis可以隨時處理單個請求,因此所有請求都是按順序處理的。這與Node.js的工作方式非常相似。所有的輸出通常不會覺得慢,因為處理單個請求的時間很短,但最重要的是這些產品被設計成非阻塞的系統調用,比如從套接字讀取或寫入數據。
我提到Redis從2.4版本開始幾乎是單線程的。我們使用線程在後臺運行壹些低效的I/O操作,主要是與硬盤I/O相關的,但這並不能改變Redis使用單壹線程處理所有請求的事實。
低效操作導致的延遲
單線程的壹個結果是,當請求執行緩慢時,其他客戶端調用必須等待請求執行。在執行GET、SET或LPUSH命令時,這不是問題,因為這些操作可以在很短的恒定時間內完成。但是,對於包含多個元素的操作,如sort、lrem和union,需要很長時間來跨越兩個大型數據集。文檔中提到了所有運算的算法復雜度。在使用之前,最好先檢查壹下您不熟悉的命令。
如果妳對延遲有要求,那麽就不要執行涉及多個元素的慢速操作。您可以使用Redis的復制功能將所有這類緩慢的操作放在replica上。您可以使用Redis的慢速日誌來監控慢速操作。此外,您可以使用您喜歡的過程監控程序(top、htop、prstat等...)來快速檢查Redis進程的CPU利用率。如果流量不高,CPU使用率高,大概就是運行慢了。
延遲是由分叉產生的。
Redis要麽在後臺生成壹個RDB文件,要麽在啟用AOF持久性模式時重寫Ap。
Pend Only文件,後臺會有壹個進程fork。fork操作(在主線程中執行)本身會導致延遲。在大多數類unix操作系統中,Fork是壹個開銷很大的操作,因為它涉及到復制許多與進程相關的對象。這對於分頁表與虛擬內存機制相關聯的系統來說尤其明顯。
對於運行在linux/AMD64系統上的實例,內存將根據每頁4KB的大小進行分頁。為了實現虛擬地址到物理地址的轉換,每個進程都會存儲壹個分頁表(樹形表示),分頁表至少會包含壹個指向進程地址空間的指針。因此,壹個空間大小為24GB的redis實例需要24GB/4KB*8 = 48MB的分頁表大小。當執行後臺保存命令時,實例將啟動壹個新線程來申請和復制48MB的內存空間。這將消耗壹些時間和CPU資源,尤其是在虛擬機上申請和初始化大內存空間時。
不同系統中的分叉時間
除了Xen系統,現代硬件都可以快速完美的復制頁表。Xen系統的問題不是具體的虛擬化,而是具體的Xen。比如用VMware或者Virutal Box不會導致分叉時間慢。下面的列表比較了不同Redis實例的分叉時間。數據包含正在執行的BGSAVE,latest_fork_usecfiled通過INFO指令查看。
VMware 6.0 GB RSS上的Linux beefy VM分叉77微秒(每GB 12.8微秒)。
運行在物理機上的Linux(硬件未知)6.1 GB RSS分叉80微秒(每GB 13.1微秒)。
運行在物理機器(Xeon @ 2.27 GHz)上的Linux 6.9 GB RSS分叉為62微秒(每GB 9微秒)。
Linux VM on 6 sync (KVM) 360 MB RSS在8.2微秒內分叉(每GB 23.3微秒)。
EC2 (Xen)上的Linux VM 6.1 GB RSS分叉1.460微秒(每GB 239.3微秒)。
linode (Xen) 0.9 GB RSS上的Linux VM分叉為382微秒(每GB 424微秒)。
您可以看到,Xen上運行的虛擬機的Redis性能相差壹兩個數量級。我們認為這是Xen系統的壹個驗證問題,我們希望這個問題能夠盡快得到處理。
交換(操作系統分頁)導致的延遲
Linux(和其他壹些操作系統)可以在硬盤上存儲內存頁面,反之亦然。這種機制能夠更有效地使用內存。如果內存頁被系統移動到交換文件中,並且這個內存頁中的數據恰好被redis使用(例如,訪問存儲在內存頁中的壹個鍵),系統將掛起redis進程,直到所需的頁面數據被重新加載到內存中。此操作很慢,因為它涉及隨機I/O,這將導致不可預測的延遲。
系統在內存和硬盤之間替換redis頁面數據主要有三個原因:
系統總是要應對內存不足的壓力,因為每個運行的進程都想申請更多的物理內存,而申請的內存量往往會超過實際的內存。簡單地說,redis總是使用比可用內存更多的內存。
redis實例的數據,或者某些數據,可能是客戶端無法訪問的,所以系統可以把這些閑置的數據替換到硬盤上。所有數據都需要存儲在內存中的情況非常罕見。
有些進程會產生大量的讀寫I/O,因為文件通常都有緩存,這往往會導致文件緩存增加,然後發生交換。請註意,redis RDB和AOF後臺線程都會生成大量文件。
幸運的是,Linux提供了壹個很好的工具來診斷這個問題,所以當懷疑延遲是由swap引起時,最簡單的方法就是使用Linux提供的工具進行診斷。
首先要做的是檢查從交換到硬盤的redis內存量。為此,我們需要知道redis實例的進程id:
$ redis-cli信息| grep進程id
進程id:5454
輸入進程目錄:
$ cd /proc/5454在這裏妳會找到壹個名為smaps的文件,它描述了redis進程的內存布局(假設妳使用的是Linux 2.6.16或更高版本)。這個文件包含許多進程使用的內存的詳細信息,其中壹個進程叫做Swap,這正是我們所關心的。但是只看這壹項是不夠的,因為smaps文件包含了redis進程的幾個不同內存映射區的用法(進程的內存布局遠不是線性排列那麽簡單)。
既然我們對所有進程的內存交換感興趣,那麽首先要做的就是使用grep命令顯示進程的smaps文件。
$ cat smaps | grep 'Swap:'
交換空間:0 kB
交換空間:0 kB
交換空間:0 kB
交換空間:0 kB
交換空間:0 kB
交換空間:12 kB
交換空間:156 kB
交換空間:8 kB
交換空間:0 kB
交換空間:0 kB
交換空間:0 kB
交換空間:0 kB
交換空間:0 kB
交換空間:0 kB
交換空間:0 kB
交換空間:0 kB
交換空間:0 kB
交換空間:4 kB
交換空間:0 kB
交換空間:0 kB
交換空間:4 kB
交換空間:0 kB
交換空間:0 kB
交換空間:4 kB
交換空間:4 kB
交換空間:0 kB
交換空間:0 kB
交換空間:0 kB
交換空間:0 kB
Swap: 0 kB如果所有數據顯示為0 kB或者部分數據偶爾顯示為4kb,說明目前壹切正常。其實我們舉的例子是壹個真實的網站,運行Redis,每秒服務幾百個用戶,會顯示更多的交換頁面。為了研究是否存在嚴重的問題,我們更改命令以打印出分配的內存大小。
$ cat smaps | egrep '^(Swap|Size)'
大小:316 kB
交換空間:0 kB
大小:4 kB
交換空間:0 kB
大小:8 kB
交換空間:0 kB
大小:40千字節
交換空間:0 kB
大小:132 kB
交換空間:0 kB
大小:720896 kB
交換空間:12 kB
大小:4096 kB
交換空間:156 kB
大小:4096 kB
交換空間:8 kB
大小:4096 kB
交換空間:0 kB
大小:4 kB
交換空間:0 kB
大小:1272 kB
交換空間:0 kB
大小:8 kB
交換空間:0 kB
大小:4 kB
交換空間:0 kB
大小:16 kB
交換空間:0 kB
大小:84 kB
交換空間:0 kB
大小:4 kB
交換空間:0 kB
大小:4 kB
交換空間:0 kB
大小:8 kB
交換空間:4 kB
大小:8 kB
交換空間:0 kB
大小:4 kB
交換空間:0 kB
大小:4 kB
交換空間:4 kB
大小:144 kB
交換空間:0 kB
大小:4 kB
交換空間:0 kB
大小:4 kB
交換空間:4 kB
大小:12 kB
交換空間:4 kB
大小:108 kB
交換空間:0 kB
大小:4 kB
交換空間:0 kB
大小:4 kB
交換空間:0 kB
大小:272 kB
交換空間:0 kB
大小:4 kB
交換空間:0 kB
在輸出信息中,您可以看到有壹個720896kb的內存分配(有壹個65,438+02 KB的交換),壹個156kb的交換屬於另壹個進程。基本上我們的內存只會有很小的內存交換,所以不會有問題。
如果進程的相當壹部分內存花在交換上,那麽您的延遲可能與交換有關。如果redis出現這種情況,您可以使用vmstat命令來驗證猜測:
$ vmstat 1
處理器-內存- -交換--io--系統--CPU--
r b swpd空閑緩沖區高速緩存si so bi bo in cs us sy id wa
0 0 3980 697932 147180 1406456 0 0 2 2 2 0 4 4 91 0
0 0 3980 697428 147180 1406580 0 0 0 0 19088 16104 9 6 84 0
0 0 3980 697296 147180 1406616 0 0 0 28 18936 16193 7 6 87 0
0 0 3980 697048 147180 1406640 0 0 0 0 18613 15987 6 6 88 0
2 0 3980 696924 147180 1406656 0 0 0 0 18744 16299 6 5 88 0
0 0 3980 697048 147180 1406688 0 0 0 4 18520 15974 6 6 88 0
輸出中我們最感興趣的兩行是si和so,它們分別統計從交換文件中恢復的內存量和從交換文件中恢復的內存量。如果在這兩行中發現非零值,則表示系統被交換。
最後,您可以使用iostat命令來查看系統的全局I/O行為。
$ iostat -xk 1
平均CPU:%用戶%好的%系統%低等待%偷用%空閑
13.55 0.04 2.92 0.53 0.00 82.95
設備:rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-SZ avgqu-SZ await SVC TM % util
sda 0.77 0.00 0.01 0.00 0.40 0.00 73.65 0.00 3.62 2.58 0.00
深發展1.27 4.75 0.82 3.54 38.00 32.32 32.19 0.11 24.80 4.24 1.85
如果確認延遲是由swap引起的,那麽就需要降低系統的內存壓力,要麽給機器增加更多內存,要麽不在同壹臺機器上運行其他消耗內存的程序。
轉載,僅供參考,祝您愉快,滿意請采納。