首頁  >  文章  >  資料庫  >  Redis內存過大會怎麼樣

Redis內存過大會怎麼樣

PHPz
PHPz轉載
2023-05-26 23:19:041533瀏覽

1 主庫宕機

先來看一下主庫宕機容災過程:如下圖

Redis內存過大會怎麼樣

##在主庫宕機的時候,我們最常見的容災策略為「切主」。具體為從該叢集剩餘從庫中選出一個從庫並將其升級為主庫,該從庫升級為主庫後再將剩餘從庫掛載至其下成為其從庫,最終恢復整個主從集群結構。

以上是一個完整的容災過程,而代價***的過程為從函式庫的重新掛載,而非主函式庫的切換。

這是因為redis無法像mysql、mongodb那樣基於同步的點位在主庫發生變化後從新的主庫繼續同步資料。 在redis叢集中一旦從庫換主,redis的做法是將更換主庫的從庫清空然後從新主庫完整同步一份資料再進行續傳。

整個從庫重做流程是這樣的:

  1. 主庫bgsave自身資料到磁碟

  2. 主庫發送rdb檔案到從庫

  3. 從庫開始載入

  4. #載入完畢開始續傳,同時開始提供服務

很明顯,在這個過程中redis的記憶體體積越大以上每一個步驟的時間都會被拉長,實際測試的資料如下(我們自認我們的機器效能比較好):

Redis內存過大會怎麼樣

可以看到,當資料達到20G的時候,一個從庫的恢復時間已經被拉長到了將近20分鐘,如果有10個從庫那麼如果依次恢復則共需200分鐘,而如果此時該從庫承擔著大量的讀取請求你能夠忍受這麼長的恢復時間嗎?

看到這裡你肯定會問:為什麼不能同時重做所有從庫?這是因為所有從庫如果同時向主庫請求rdb檔案那麼主庫的網卡則立即跑滿從而進入一個無法正常提供服務的狀態,此時主庫又死了,簡直是雪上加霜。

當然,我們可以批次恢復從庫,例如兩兩一組,那麼全部從庫的恢復時間也僅僅從200分鐘降低到了100分鐘,這不是五十步笑百步嗎?

另一個重要問題在於第四點中的標紅位置,續傳可以理解為一個簡化的mongodb的oplog,它是一個體積固定的記憶體空間,我們稱之為「同步緩衝區」。

redis主庫的寫入操作都會在該區域存放一份然後發送給從庫,而如果在上文中1,2,3步耗時太久那麼很可能這個同步緩衝區就被重寫,此時從函式庫無法找到對應的續傳位置它會怎麼做?答案是重做1,2,3步!

但因為我們無法解決1,2,3步的耗時因此該從庫會永遠的進入惡性循環:不停的向主庫請求完整數據,結果對主庫的網卡造成嚴重影響。

2 擴容問題

很多時候會出現流量的突發性成長,通常在找到原因之前我們的緊急做法就是擴容了。

而根據場景一中的表格,一個20G的redis擴容一個從庫需要將近20分鐘,在這個緊急的時刻20分鐘業務能夠容忍嗎?可能還沒擴好就死翹翹了。

3 網路不好導致從庫重做最終引發雪崩

該場景的***問題是主庫與從庫的同步中斷,而此時很可能從庫仍然在接受寫入請求,那麼一旦中斷時間過長同步緩衝區就很可能被複寫。此時從庫上一次的同步位置已遺失,在網路恢復後雖然主庫沒有發生變化但由於從庫的同步位置丟失了從庫必須進行重做,也就是問題一中的1,2,3, 4步。如果此時主庫內存體積過大那麼從庫重做速度就會很慢,而發送到從庫的讀取請求就會受到嚴重影響,同時由於傳輸的rdb文件的體積過大,主庫的網卡在相當長的一段時間都會受到嚴重影響。

4 記憶體越大,觸發持久化的操作阻塞主執行緒的時間越長

Redis是單執行緒的記憶體資料庫,在redis需要執行耗時的操作時,會fork一個新程序來做,例如bgsave,bgrewriteaof。 Fork新進程時,雖然可共享的資料內容不需要複製,但會複製先前進程空間的記憶體頁表,這個複製是主執行緒來做的,會阻塞所有的讀寫操作,並且隨著記憶體使用量越大耗時越長。例如:記憶體20G的redis,bgsave複製記憶體頁表耗時約750ms,redis主執行緒也會因為它阻塞750ms。

解決方法

解決方法當然就是極力減少記憶體的使用了,一般情況下,我們都是這麼做的:

#1 設定過期時間

對具有時效性的key設定過期時間,透過redis自身的過期key清理策略來降低過期key對於記憶體的佔用,同時也能夠減少業務的麻煩,不需要定期清理了

2 不存放垃圾到redis中

這簡直就是廢話,但是,有跟我們同病相憐的人麼?

#3 及時清理無用數據

例如一個redis承載了3個業務的數據,一段時間後有2個業務下線了,那你就把這兩個業務的相關數據清理了唄

4 盡量對數據進行壓縮

例如一些長文本形式的數據,壓縮能夠大幅降低記憶體佔用

5 專注於記憶體成長並定位大容量key

不管是DBA還是開發人員,你用redis,你就必須關注內存,否則,你其實就是不稱職的,這裡可以分析redis實例中哪些key比較大從而幫助業務快速定位異常key(非預期增長的key,往往是問題之源)

6 pika

如果實在不想搞的那麼累,那就把業務遷移到新開源的pika上面,這樣就不用太關注記憶體了,redis記憶體太大引發的問題,那也都不是問題了。

以上是Redis內存過大會怎麼樣的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除