標籤:blog http io os ar 使用 for sp strong
在使用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 nsBranch mispredict 5 nsL2 cache reference 7 ns 14x L1 cacheMutex lock/unlock 25 nsMain memory reference 100 ns 20x L2 cache, 200x L1 cacheCompress 1K bytes with Zippy 3,000 nsSend 1K bytes over 1 Gbps network 10,000 ns 0.01 msRead 4K randomly from SSD* 150,000 ns 0.15 msRead 1 MB sequentially from memory 250,000 ns 0.25 msRound trip within same datacenter 500,000 ns 0.5 msRead 1 MB sequentially from SSD* 1,000,000 ns 1 ms 4X memoryDisk seek 10,000,000 ns 10 ms 20x datacenter roundtripRead 1 MB sequentially from disk 20,000,000 ns 20 ms 80x memory, 20X SSDSend packet CA->Netherlands->CA 150,000,000 ns 150 ms Notes-----1 ns = 10-9 seconds1 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/2843375Great ‘humanized‘ comparison version:https://gist.github.com/2843375Visual comparison chart: http://i.imgur.com/k0t1e.pngNice 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
Redis錯誤配置詳解