【編者按】筆者在運行了上千個Redis數(shù)據(jù)庫實例后,不僅發(fā)現(xiàn)了使用Redis時遇到的一些令人頭疼的問題,更是探索到了解決這些問題的簡單解決方案,其中包括復制緩沖區(qū)限制、復制超時和客戶端緩沖區(qū)等一系列容易遇到的難題。
免費訂閱“CSDN大數(shù)據(jù)”微信公眾號,實時了解最新的大數(shù)據(jù)進展!
CSDN大數(shù)據(jù),專注大數(shù)據(jù)資訊、技術和經(jīng)驗的分享和討論,提供Hadoop、Spark、Imapala、Storm、HBase、MongoDB、Solr、機器學習、智能算法等相關大數(shù)據(jù)觀點,大數(shù)據(jù)技術,大數(shù)據(jù)平臺,大數(shù)據(jù)實踐,大數(shù)據(jù)產(chǎn)業(yè)資訊等服務。
以下為譯文:
Redis提供了許多提高和維護高效內(nèi)存數(shù)據(jù)庫使用的工具。在無需額外配置應用層的前提下,Redis獨特的數(shù)據(jù)類型、指令和命令調(diào)優(yōu)就可以滿足應用的需求,但是錯誤的配置,更確切的說那些機外設備可能導致操作麻煩和性能問題。雖然導致了一些令人頭疼的問題,但是解決方案是存在的,而且解決方案可能比我們預期的簡單。
本系列文章介紹了使用Redis時遇到的一些令人頭疼的問題,以及該解決這些問題。這些內(nèi)容基于我們在運行上千個Redis數(shù)據(jù)庫實例時的真實經(jīng)歷。
復制緩沖區(qū)限制
復制緩沖區(qū)主從服務器同步數(shù)據(jù)時保存數(shù)據(jù)的內(nèi)存區(qū)域。在一個完整的主從同步中,初始化階段同步時,主服務器在復制緩沖區(qū)中保存數(shù)據(jù)的變化。初始化階段完成后,緩沖的內(nèi)容發(fā)送到從服務器。這個過程可能會遇到緩沖區(qū)的容量限制,達到最大容量時復制會重新開始。為了避免這種情況,緩沖區(qū)需要依據(jù)復制過程中變化的類型和數(shù)量進行初始化配置。例如,一個小緩沖區(qū)可以存儲少量的變化數(shù)據(jù),但當變化比較多、比較大時,我們需要大緩沖區(qū)。一個更復雜的解決方案會更詳細的設置緩沖區(qū),避免冗長、大的復雜過程耗盡緩沖區(qū)(如果緩沖區(qū)太小)。最終,這個解決方案需要微調(diào)特定的數(shù)據(jù)庫。
當256MB的硬限制到達時,或者軟限制到達且持續(xù)60秒時,默認的復制鏈路會斷裂(導致同步從頭開始)。許多情況下,特別是寫負載高和從服務器帶寬不足的情況下,負載過程都無法結束。這可能導致無限循環(huán),主Redis持續(xù)的將整個數(shù)據(jù)集復制到硬盤,這可以導致高速率的I/O操作,消耗高達三倍的額外內(nèi)存。此外,無限循環(huán)將導致從服務器無法趕上主服務器,無法與主服務器完全同步。
一個簡單地解決方案是提高輸出從緩沖區(qū),將軟硬限制都設置為512MB,這個解決方案可以很快的提高結果。
因為有很多重新配置,所以務必理解:
1. 在增加復制緩沖區(qū)尺寸前,我們必須確保機器上有足夠的內(nèi)存。
2. Redis內(nèi)存使用計算不考慮復制緩沖區(qū)容量。
以上是本文介紹的第一個問題。如我們上面談到的,盡管有復制緩沖區(qū)限制,合適的配置是可以良好運行的。下面我們談談主從復制的另一問題。我們將深入討論完成該過程所需的時間和可能導致麻煩的一些配置問題。
復制超時
如我們先前討論的,Redis的復制過程包括兩個同步階段:初始化階段和進行階段。盡管進行階段很穩(wěn)定(只要保持主從服務器間的鏈路即可),初始化階段不那么容易完成。成功的完成初始化同步不止依賴于復制緩沖區(qū)分配的內(nèi)存,還基于該步驟花費的時間。
你可能想起來了,初始化同步步驟包括后臺保存以及整個數(shù)據(jù)主導從的傳播。基于數(shù)據(jù)庫容量和網(wǎng)絡連接質(zhì)量,這可能是一個很長的過程。如果階段耗時太久,Redis可能會達到復制超時設置,這可能會導致初始階段重復進行。這種情況下,你會發(fā)現(xiàn)從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”)。這個時間可能很短,特別是當你有:
我們可以通過將復制超時設置為更合適的值來修正這個問題。首先是一個可接受復制數(shù)據(jù)庫的的估計時間。第一步,檢查Redis通過BGSAVE指令和檢查相關行(如“Background saving started by pid nnn ”表示進程開始,“ Background saving terminated with success”表示進程結束)的日志文檔執(zhí)行后臺進程所花的時間。然后,測量CN將主服務器上的結果RDB文件拷貝到從服務器硬盤所需的時間。最后,測量從硬盤加載數(shù)據(jù)實際消耗的時間(如重啟Redis,在日志文件中尋找“DB loaded from disk”行)。這些方法可以大致估計復制超時值,保險起見,我們可能需要在上面加上10~20%。
依據(jù)測量值設定了超時后,我們可以通過讓從服務器執(zhí)行幾次完整的同步和檢查日志文件來測量復制的實際耗時。如果可能的話,在日常不同的時刻重復這個操作,確保在不同的負載下系統(tǒng)的表現(xiàn)良好。最后,切記隨著數(shù)據(jù)庫的增長,我們需要定時檢查超時設置值。
以上描述的是Redis復制問題。復制是保持數(shù)據(jù)庫可用、擴展數(shù)據(jù)庫可讀性的有力工具,不過注意復制的默認設置,確保依照實際使用情況配置數(shù)據(jù)庫。下面我們談談客戶端緩沖區(qū)。在有些情況下,客戶端緩沖區(qū)會帶來很多問題。
客戶端緩沖區(qū)
你大概已經(jīng)知道Redis是一個內(nèi)存數(shù)據(jù)庫,這意味著所有的數(shù)據(jù)都由RAM直接管理和提供的。因此Redis有著卓越的交付性能,Redis可以以亞毫秒級的延遲處理幾萬、幾十萬的請求。RAM是當下最快的存儲技術――為了更好的理解延遲數(shù)字,請看以下數(shù)據(jù):
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,如同它的名字和設計,是一個移動服務器,客戶端(通常)通過網(wǎng)絡連接Redis。這種情況下,客戶端請求返回客戶端的時間將顯著長于Redis CPU從RAM讀取數(shù)據(jù)的時間。這意味著如果沒有客戶端緩沖區(qū)的話,Redis的主要差異與在該段時間對服務的響應有關。
客戶端緩沖區(qū)組成了服務客戶請求所需的內(nèi)存空間,Redis的每個連接都配有自己的緩沖區(qū)空間。處理請求后,Redis把響應數(shù)據(jù)復制到客戶端緩沖區(qū),然后繼續(xù)處理下一個請求,與此同時,請求客戶端通過網(wǎng)絡連接讀取數(shù)據(jù)。Redis客戶端緩沖區(qū)配置在redis.conf文件,通過client-output-buffer-limit normal指令配置(你可以在運行時通過config get client-output-buffer-limit指令獲取設置)。默認的redis.conf文件定義如下:
client-output-buffer-limit normal 0 0 0
這些數(shù)值分別代表緩沖區(qū)軟限制,硬限制和以秒為單位的超時(類似于復制緩沖區(qū))。當Redis終止連接時,這些值提供保護――不需要客戶讀取回復――當緩沖區(qū)尺寸達到a)軟限制并且保持狀態(tài)直到超時b)硬限制。將這些數(shù)值都設為0意味著關閉保護。
不過,和復制緩沖區(qū)不同的是客戶端緩沖區(qū)來自Redis數(shù)據(jù)內(nèi)存空間。可以通過maxmemory指令設置Redis的總內(nèi)存值,達到極限后,Redis將應用其配置的驅逐策略(由maxmemory-policy 指令定義)。因此,低性能的客戶或大量的同時連接可能會因為數(shù)據(jù)集尺寸和客戶端緩沖區(qū)達到內(nèi)存限制導致Redis實例過早的驅逐鍵或禁止更新。
由于生命周期的相對性,一個客戶端不需要降低性能就可能導致這種現(xiàn)象。因為RAM讀取和網(wǎng)絡讀取存在著很大的速度差異,過多的客戶端緩沖區(qū)很可能耗盡Redis內(nèi)存,即使是在高性能的客戶端和網(wǎng)絡連接中。例如,考慮下(萬惡的)KEYS指令,這個指令觸發(fā)后,Redis將會把整個鍵的名空間拷貝給客戶端緩沖區(qū)。如果我們的數(shù)據(jù)庫有很多鍵,這很可能導致驅逐。
警告:使用KEYS時務必要謹慎,不要在生產(chǎn)環(huán)境下使用KEYS。使用KEYS除了可能導致上文提到的驅逐外,還可能會在很長時間內(nèi)封鎖Redis。
KEYS不是唯一一個可能導致這種情況的指令。類似的指令還有SMEMBERS,HGETALL,LRANGE和ZRANGE(以及與這些指令相關的指令),當值(或范圍)足夠大,或者當有很多公開連接(每個連接都需要單獨的緩沖區(qū))時,這些指令可能導致類似的現(xiàn)象。
我們強烈推薦謹慎負責的使用這些指令。我們推薦大家使用SCAN家族指令替代這些指令,v2.8版本加入了SCAN指令。SCAN指令不僅允許Redis在后續(xù)的SCAN調(diào)用間繼續(xù)處理請求,還降低了耗盡客戶端緩沖區(qū)的概率。
客戶端緩沖區(qū)是Redis內(nèi)存需求和管理常常會忽略的方面。客戶端緩沖區(qū)的默認設置有風險,很可能導致內(nèi)存耗盡。我們要有依據(jù)的設置緩沖區(qū)閾值―考慮“maxmemory”設置,當下和預測內(nèi)存使用,應用流量模式。謹慎的使用先前提到的指令可以避免那些令人頭疼的問題。歡迎關注我們后續(xù)的文章。
原文鏈接:
Top Redis Headaches for Devops