Redis錯誤配置詳解


在使用Redis做緩存時,應用往往能得到非常高的性能。然而,如果配置不當,你將遇到很多令人頭疼的問題,比如復制緩沖區限制、復制超時等。

 

Redis提供了許多提高和維護高效內存數據庫使用的工具。在無需額外配置應用層的前提下,Redis獨特的數據類型、指令和命令調優就可以滿足應用的需求,但是錯誤的配置,更確切的說那些機外設備可能導致操作麻煩和性能問題。雖然導致了一些令人頭疼的問題,但是解決方案是存在的,而且解決方案可能比我們預期的簡單。

本系列文章介紹了使用Redis時遇到的一些令人頭疼的問題,以及該解決這些問題。這些內容基於我們在運行上千個Redis數據庫實例時的真實經歷。

復制緩沖區限制

復制緩沖區主從服務器同步數據時保存數據的內存區域。在一個完整的主從同步中,初始化階段同步時,主服務器在復制緩沖區中保存數據的變化。初始化階段完成后,緩沖的內容發送到從服務器。這個過程可能會遇到緩沖區的容量限制,達到最大容量時復制會重新開始。為了避免這種情況,緩沖區需要依據復制過程中變化的類型和數量進行初始化配置。例如,一個小緩沖區可以存儲少量的變化數據,但當變化比較多、比較大時,我們需要大緩沖區。一個更復雜的解決方案會更詳細的設置緩沖區,避免冗長、大的復雜過程耗盡緩沖區(如果緩沖區太小)。最終,這個解決方案需要微調特定的數據庫。

當256MB的硬限制到達時,或者軟限制到達且持續60秒時,默認的復制鏈路會斷裂(導致同步從頭開始)。許多情況下,特別是寫負載高和從服務器帶寬不足的情況下,負載過程都無法結束。這可能導致無限循環,主Redis持續的將整個數據集復制到硬盤,這可以導致高速率的I/O操作,消耗高達三倍的額外內存。此外,無限循環將導致從服務器無法趕上主服務器,無法與主服務器完全同步。

一個簡單地解決方案是提高輸出從緩沖區,將軟硬限制都設置為512MB,這個解決方案可以很快的提高結果。

因為有很多重新配置,所以務必理解:

1.  在增加復制緩沖區尺寸前,我們必須確保機器上有足夠的內存。

2.  Redis內存使用計算不考慮復制緩沖區容量。

以上是本文介紹的第一個問題。如我們上面談到的,盡管有復制緩沖區限制,合適的配置是可以良好運行的。下面我們談談主從復制的另一問題。我們將深入討論完成該過程所需的時間和可能導致麻煩的一些配置問題。

復制超時

如我們先前討論的,Redis的復制過程包括兩個同步階段:初始化階段和進行階段。盡管進行階段很穩定(只要保持主從服務器間的鏈路即可),初始化階段不那么容易完成。成功的完成初始化同步不止依賴於復制緩沖區分配的內存,還基於該步驟花費的時間。

你可能想起來了,初始化同步步驟包括后台保存以及整個數據主導從的傳播。基於數據庫容量和網絡連接質量,這可能是一個很長的過程。如果階段耗時太久,Redis可能會達到復制超時設置,這可能會導致初始階段重復進行。這種情況下,你會發現從Redis日志文檔充斥着這些信息:

 

[28618] 21 Jul 00:33:36.031 * Connecting to MASTER 10.60.228.106:25994 
[28618] 21 Jul 00:33:36.032 * MASTER <-> SLAVE sync started 
[28618] 21 Jul 00:33:36.032 * Non blocking connect for SYNC fired the event. 
[28618] 21 Jul 00:33:36.032 * Master replied to PING, replication can continue... 
[28618] 21 Jul 00:33:36.032 * Partial resynchronization not possible (no cached master) 
[28618] 21 Jul 00:33:36.032 * Full resync from master: 549907b03661629665eb90846ea921f23de6c961:2537453 

 

Redis復制超時的默認值是60秒(見redis.conf文件的repl-timeout指令,或使用redis-cli運行“config get repl-timeout”)。這個時間可能很短,特別是當你有:

 

  • 低速存儲器:如果主服務器或從服務器是基於低速存儲器的,如果是主服務器將導致后台進程花費很多時間;如果是服務器磁盤讀寫數據時間將延長。
  • 大數據集:更大的數據集將需要更長的存儲時間和傳輸時間。
  • 網絡性能:當主服務器和從服務器的網絡鏈路有限制帶寬和高延遲時,這會直接影響數據傳輸傳輸速率。

 

我們可以通過將復制超時設置為更合適的值來修正這個問題。首先是一個可接受復制數據庫的的估計時間。第一步,檢查Redis通過BGSAVE指令和檢查相關行(如“Background saving started by pid nnn ”表示進程開始,“ Background saving terminated with success”表示進程結束)的日志文檔執行后台進程所花的時間。然后,測量CN將主服務器上的結果RDB文件拷貝到從服務器硬盤所需的時間。最后,測量從硬盤加載數據實際消耗的時間(如重啟Redis,在日志文件中尋找“DB loaded from disk”行)。這些方法可以大致估計復制超時值,保險起見,我們可能需要在上面加上10~20%。

依據測量值設定了超時后,我們可以通過讓從服務器執行幾次完整的同步和檢查日志文件來測量復制的實際耗時。如果可能的話,在日常不同的時刻重復這個操作,確保在不同的負載下系統的表現良好。最后,切記隨着數據庫的增長,我們需要定時檢查超時設置值。

以上描述的是Redis復制問題。復制是保持數據庫可用、擴展數據庫可讀性的有力工具,不過注意復制的默認設置,確保依照實際使用情況配置數據庫。下面我們談談客戶端緩沖區。在有些情況下,客戶端緩沖區會帶來很多問題。

客戶端緩沖區

你大概已經知道Redis是一個內存數據庫,這意味着所有的數據都由RAM直接管理和提供的。因此Redis有着卓越的交付性能,Redis可以以亞毫秒級的延遲處理幾萬、幾十萬的請求。RAM是當下最快的存儲技術——為了更好的理解延遲數字,請看以下數據:

 

Latency Comparison Numbers
--------------------------
L1 cache reference 0.5 ns
Branch mispredict 5 ns
L2 cache reference 7 ns 14x L1 cache
Mutex lock/unlock 25 ns
Main memory reference 100 ns 20x L2 cache, 200x L1 cache
Compress 1K bytes with Zippy 3,000 ns
Send 1K bytes over 1 Gbps network 10,000 ns 0.01 ms
Read 4K randomly from SSD* 150,000 ns 0.15 ms
Read 1 MB sequentially from memory 250,000 ns 0.25 ms
Round trip within same datacenter 500,000 ns 0.5 ms
Read 1 MB sequentially from SSD* 1,000,000 ns 1 ms 4X memory
Disk seek 10,000,000 ns 10 ms 20x datacenter roundtrip
Read 1 MB sequentially from disk 20,000,000 ns 20 ms 80x memory, 20X SSD
Send packet CA->Netherlands->CA 150,000,000 ns 150 ms
 
Notes
-----
1 ns = 10-9 seconds
1 ms = 10-3 seconds
* Assuming ~1GB/sec SSD
 
Credit
------
By Jeff Dean: http://research.google.com/people/jeff/
Originally by Peter Norvig: http://norvig.com/21-days.html#answers
 
Contributions
-------------
Some updates from: https://gist.github.com/2843375
Great 'humanized' comparison version:https://gist.github.com/2843375
Visual comparison chart: http://i.imgur.com/k0t1e.png
Nice animated presentation of the data: http://prezi.com/pdkvgys-r0y6/latency-numbers-for-programmers-web-development/
- See more at:http://redislabs.com/blog/top-redis-headaches-for-devops-client-buffers#sthash.9rHluMPF.dpuf

 

Redis,如同它的名字和設計,是一個移動服務器,客戶端(通常)通過網絡連接Redis。這種情況下,客戶端請求返回客戶端的時間將顯著長於Redis CPU從RAM讀取數據的時間。這意味着如果沒有客戶端緩沖區的話,Redis的主要差異與在該段時間對服務的響應有關。

客戶端緩沖區組成了服務客戶請求所需的內存空間,Redis的每個連接都配有自己的緩沖區空間。處理請求后,Redis把響應數據復制到客戶端緩沖區,然后繼續處理下一個請求,與此同時,請求客戶端通過網絡連接讀取數據。Redis客戶端緩沖區配置在redis.conf文件,通過client-output-buffer-limit normal指令配置(你可以在運行時通過config get client-output-buffer-limit指令獲取設置)。默認的redis.conf文件定義如下:

client-output-buffer-limit normal 0 0 0

這些數值分別代表緩沖區軟限制,硬限制和以秒為單位的超時(類似於復制緩沖區)。當Redis終止連接時,這些值提供保護——不需要客戶讀取回復——當緩沖區尺寸達到a)軟限制並且保持狀態直到超時b)硬限制。將這些數值都設為0意味着關閉保護。

不過,和復制緩沖區不同的是客戶端緩沖區來自Redis數據內存空間。可以通過maxmemory指令設置Redis的總內存值,達到極限后,Redis將應用其配置的驅逐策略(由maxmemory-policy 指令定義)。因此,低性能的客戶或大量的同時連接可能會因為數據集尺寸和客戶端緩沖區達到內存限制導致Redis實例過早的驅逐鍵或禁止更新。

由於生命周期的相對性,一個客戶端不需要降低性能就可能導致這種現象。因為RAM讀取和網絡讀取存在着很大的速度差異,過多的客戶端緩沖區很可能耗盡Redis內存,即使是在高性能的客戶端和網絡連接中。例如,考慮下(萬惡的)KEYS指令,這個指令觸發后,Redis將會把整個鍵的名空間拷貝給客戶端緩沖區。如果我們的數據庫有很多鍵,這很可能導致驅逐。

警告:使用KEYS時務必要謹慎,不要在生產環境下使用KEYS。使用KEYS除了可能導致上文提到的驅逐外,還可能會在很長時間內封鎖Redis。

KEYS不是唯一一個可能導致這種情況的指令。類似的指令還有SMEMBERS,HGETALL,LRANGE和ZRANGE(以及與這些指令相關的指令),當值(或范圍)足夠大,或者當有很多公開連接(每個連接都需要單獨的緩沖區)時,這些指令可能導致類似的現象。

我們強烈推薦謹慎負責的使用這些指令。我們推薦大家使用SCAN家族指令替代這些指令,v2.8版本加入了SCAN指令。SCAN指令不僅允許Redis在后續的SCAN調用間繼續處理請求,還降低了耗盡客戶端緩沖區的概率。

客戶端緩沖區是Redis內存需求和管理常常會忽略的方面。客戶端緩沖區的默認設置有風險,很可能導致內存耗盡。我們要有依據的設置緩沖區閾值—考慮“maxmemory”設置,當下和預測內存使用,應用流量模式。謹慎的使用先前提到的指令可以避免那些令人頭疼的問題。歡迎關注我們后續的文章。

原文鏈接:

Top Redis Headaches for Devops – Client Buffers

Top Redis Headaches for Devops – Replication Timeouts

Top Redis Headaches for Devops – Client Buffers(翻譯/仁君 責編/仲浩)

 

http://www.csdn.net/article/2014-07-31/2820964


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM