20 | 刪除數(shù)據(jù)后,為什么內(nèi)存占用率還是很高径荔?
1、前言
這樣一個問題:明明做了數(shù)據(jù)刪除脆霎,數(shù)據(jù)量已經(jīng)不大了总处,為什么使用 top 命令查看時,還會發(fā)現(xiàn) Redis 占用了很多內(nèi)存呢睛蛛?
因為當(dāng)數(shù)據(jù)刪除后鹦马,Redis 釋放的內(nèi)存空間會由內(nèi)存分配器管理胧谈,并不會立即返回給操作系統(tǒng)。所以荸频,操作系統(tǒng)仍然會記錄著給 Redis 分配了大量內(nèi)存菱肖。
一個潛在的風(fēng)險點:Redis 釋放的內(nèi)存空間可能并不是連續(xù)的,這些不連續(xù)的內(nèi)存空間很有可能處于一種閑置的狀態(tài)旭从。
導(dǎo)致一個問題:雖然有空閑空間稳强,Redis 卻無法用來保存數(shù)據(jù),不僅會減少 Redis 能夠?qū)嶋H保存的數(shù)據(jù)量和悦,還會降低 Redis 運行機(jī)器的成本回報率退疫。
類似的可以把 Redis 的內(nèi)存空間比作高鐵上的車廂座位數(shù)。如果高鐵的車廂座位數(shù)很多鸽素,但運送的乘客數(shù)很少褒繁,那么,高鐵運行一次的效率低付鹿,成本高澜汤,性價比就會降低,Redis 也是一樣
2舵匾、什么是內(nèi)存碎片俊抵?
通常情況下,內(nèi)存空間閑置坐梯,往往是因為操作系統(tǒng)發(fā)生了較為嚴(yán)重的內(nèi)存碎片徽诲。
首先了解什么是內(nèi)存碎片。
操作系統(tǒng)的內(nèi)存碎片:雖然操作系統(tǒng)的剩余內(nèi)存空間總量足夠吵血,但是谎替,應(yīng)用申請的是一塊連續(xù)地址空間的 N 字節(jié),但在剩余的內(nèi)存空間中蹋辅,沒有大小為 N 字節(jié)的連續(xù)空間钱贯,那么,這些剩余空間就是內(nèi)存碎片(比如上圖中的“空閑 2 字節(jié)”和“空閑 1 字節(jié)”侦另,就是這樣的碎片)秩命。
3、內(nèi)存碎片是如何形成的褒傅?
兩個原因:
1)弃锐、內(nèi)因:操作系統(tǒng)內(nèi)存分配機(jī)制。
內(nèi)因:內(nèi)存分配器的分配策略--決定了操作系統(tǒng)無法做到“按需分配”殿托。
內(nèi)存分配器一般是按固定大小來分配內(nèi)存霹菊,而不是完全按照應(yīng)用程序申請的內(nèi)存空間大小給程序分配。
Redis 可以使用 libc支竹、jemalloc旋廷、tcmalloc 多種內(nèi)存分配器來分配內(nèi)存鸠按,默認(rèn)使用 jemalloc。
jemalloc 的分配策略之一柳洋,是按照一系列固定的大小劃分內(nèi)存空間待诅,例如 8 字節(jié)、16 字節(jié)熊镣、32 字節(jié)卑雁、48 字節(jié),…, 2KB绪囱、4KB测蹲、8KB 等。當(dāng)程序申請的內(nèi)存最接近某個固定值時鬼吵,jemalloc 會給它分配相應(yīng)大小的空間扣甲。本身就會產(chǎn)生一定的碎片。
這樣分配的好處是為了減少分配次數(shù)琉挖,假設(shè)申請20K,那么會給他分配32涣脚,如果在需要10示辈,就不用再次向操作系統(tǒng)申請分配了,節(jié)省了一次分配遣蚀。
但是矾麻,如果 Redis 每次向分配器申請的內(nèi)存空間大小不一樣,這種分配方式就會有形成碎片的風(fēng)險芭梯,而這正好來源于 Redis 的外因了险耀。
2)、外因:Redis 負(fù)載特稱玖喘。
外因:鍵值對大小不一樣和刪改操作
第一個外因:Redis中鍵值對大小不一致甩牺,申請內(nèi)存空間分配時,本身就會有大小不一的空間需求
第二個外因:這些鍵值對會被修改和刪除累奈,這會導(dǎo)致空間的擴(kuò)容和釋放贬派。
一方面,如果修改后的鍵值對變大或變小了费尽,就需要占用額外的空間或者釋放不用的空間赠群。
另一方面羊始,刪除的鍵值對就不再需要內(nèi)存空間了旱幼,此時,就會把空間釋放出來突委,形成空閑空間柏卤。
一開始冬三,應(yīng)用 A、B缘缚、C勾笆、D 分別保存了 3、1桥滨、2窝爪、4 字節(jié)的數(shù)據(jù),并占據(jù)了相應(yīng)的內(nèi)存空間齐媒。然后蒲每,應(yīng)用 D 刪除了 1 個字節(jié),這個 1 字節(jié)的內(nèi)存空間就空出來了喻括。緊接著邀杏,應(yīng)用 A修改了數(shù)據(jù),從 3 字節(jié)變成了 4 字節(jié)唬血。為了保持 A 數(shù)據(jù)的空間連續(xù)性望蜡,操作系統(tǒng)就需要把 B 的數(shù)據(jù)拷貝到別的空間,比如拷貝到 D 剛剛釋放的空間中拷恨。此時脖律,應(yīng)用 C 和 D 也分別刪除了 2 字節(jié)和 1 字節(jié)的數(shù)據(jù),整個內(nèi)存空間上就分別出現(xiàn)了 2 字節(jié)和 1 字節(jié)的空閑碎片挑随。如果應(yīng)用 E 想要一個 3 字節(jié)的連續(xù)空間状您,顯然是不能得到滿足的。因為兜挨,雖然空間總量夠膏孟,但卻是碎片空間,并不是連續(xù)的拌汇。
大量內(nèi)存碎片的存在柒桑,會造成 Redis 的內(nèi)存實際利用率變低。
4噪舀、如何判斷是否有內(nèi)存碎片魁淳?
INFO memory 命令查看內(nèi)存的使用情況
INFO memory
# Memory
used_memory:1073741736
used_memory_human:1024.00M
used_memory_rss:1997159792
used_memory_rss_human:1.86G
…
mem_fragmentation_ratio:1.86
mem_fragmentation_ratio 的指標(biāo):表示的就是 Redis 當(dāng)前的內(nèi)存碎片率。
mem_fragmentation_ratio 大于 1 但小于 1.5与倡。這種情況是合理的界逛。
mem_fragmentation_ratio 大于 1.5 。這表明內(nèi)存碎片率已經(jīng)超過了 50%纺座。
mem_fragmentation_ratio = used_memory_rss/ used_memory
used_memory_rss 是操作系統(tǒng)實際分配給 Redis 的物理內(nèi)存空間息拜,里面就包含了碎片;而 used_memory 是 Redis 為了保存數(shù)據(jù)實際申請使用的空間。
5少欺、如何清理內(nèi)存碎片喳瓣?
1)、“簡單粗暴”的方法就是重啟 Redis 實例
帶來兩個后果:1)赞别、沒持久化的數(shù)據(jù)丟失畏陕;2)、恢復(fù)階段時常取決于aof仿滔、rdb文件大小惠毁,如果只有一個redis實例,那么恢復(fù)階段無法提供服務(wù)崎页。
2)仁讨、優(yōu)雅的方式:Redis 4.0 提供的?activedefrag ,啟用自動內(nèi)存碎片清理?
#將?activedefrag? 設(shè)置成yes实昨,這個命令只是啟用了自動清理功能
config set activedefrag yes?
什么時候自動清理洞豁?
受到下面這兩個參數(shù)的控制。這兩個參數(shù)分別設(shè)置了觸發(fā)內(nèi)存清理的一個條件荒给,如果同時滿足這兩個條件丈挟,就開始清理。在清理的過程中志电,只要有一個條件不滿足了曙咽,就停止自動清理。
active-defrag-ignore-bytes 100mb:表示內(nèi)存碎片的字節(jié)數(shù)達(dá)到 100MB 時挑辆,開始清理例朱;
active-defrag-threshold-lower 10:表示內(nèi)存碎片空間占操作系統(tǒng)分配給 Redis 的總空間比例達(dá)到 10% 時,開始清理鱼蝉。
除了這兩個參數(shù)洒嗤,還提供了兩個參數(shù)監(jiān)控CPU的占用時間,既保證正常清理工作魁亦,又避免了降低Redis性能渔隶。
active-defrag-cycle-min 25: 表示自動清理過程所用 CPU 時間的比例不低于25%,保證清理能正常開展洁奈;
active-defrag-cycle-max 75:表示自動清理過程所用 CPU 時間的比例不高于75%间唉,一旦超過,就停止清理利术,從而避免在清理時呈野,大量的內(nèi)存拷貝阻塞 Redis威沫,導(dǎo)致響應(yīng)延遲升高京腥。
自動內(nèi)存碎片清理機(jī)制在控制碎片清理啟停的時機(jī)上,既考慮了碎片的空間占比闷愤、對 Redis 內(nèi)存使用效率的影響,還考慮了清理機(jī)制本身的 CPU 時間占比姆打、對 Redis 性能的影響。
3)肠虽、自動清理原理
內(nèi)存碎片清理幔戏,簡單來說,就是“搬家讓位税课,合并空間”闲延。
當(dāng)有數(shù)據(jù)把一塊連續(xù)的內(nèi)存空間分割成好幾塊不連續(xù)的空間時,操作系統(tǒng)就會把數(shù)據(jù)拷貝到別處韩玩。此時垒玲,數(shù)據(jù)拷貝需要能把這些數(shù)據(jù)原來占用的空間都空出來,把原本不連續(xù)的內(nèi)存空間變成連續(xù)的空間找颓。否則合愈,如果數(shù)據(jù)拷貝后,并沒有形成連續(xù)的內(nèi)存空間击狮,這就不能算是清理了佛析。
不過需要注意:清理是有代價的,操作系統(tǒng)拷貝數(shù)據(jù)后再釋放原空間會帶來開銷彪蓬,會影響Redis性能寸莫。(因為 Redis 是單線程,在數(shù)據(jù)拷貝時档冬,Redis 只能等著膘茎,這就導(dǎo)致 Redis 無法及時處理請求,性能就會降低)
解決:Redis 專門為自動內(nèi)存碎片清理功機(jī)制設(shè)置的參數(shù)酷誓。可以通過設(shè)置參數(shù)披坏,來控制碎片清理的開始和結(jié)束時機(jī),以及占用的 CPU 比例盐数,從而減少碎片清理對 Redis 本身請求處理的性能影響刮萌。(具體看上面)
6、小節(jié)
Redis 的內(nèi)存空間效率問題娘扩,這里面的一個關(guān)鍵技術(shù)點就是要識別和處理內(nèi)存碎片着茸。簡單來說,就是“三個一”:
INFO?memory 命令是一個好工具琐旁,可以幫助你查看碎片率的情況涮阔;
碎片率閾值是一個好經(jīng)驗,可以幫忙你有效地判斷是否要進(jìn)行碎片清灰殴;
內(nèi)存碎片自動清理是一個好方法敬特,可以避免因為碎片導(dǎo)致 Redis 的內(nèi)存實際利用率降低掰邢,提升成本收益率。
小貼士:內(nèi)存碎片自動清理涉及內(nèi)存拷貝伟阔,這對 Redis 而言辣之,是個潛在的風(fēng)險。如果在實踐過程中遇到 Redis 性能變慢皱炉,記得通過日志看下是否正在進(jìn)行碎片清理怀估。如果 Redis 的確正在清理碎片,那么合搅,建議調(diào)小 active-defrag-cycle-max 的值多搀,以減輕對正常請求處理的影響。(也就是第四個監(jiān)控CPU時間的參數(shù))
21 | 緩沖區(qū):一個可能引發(fā)“慘案”的地方
1灾部、前言
緩沖區(qū)的功能其實很簡單康铭,主要就是用一塊內(nèi)存空間來暫時存放命令數(shù)據(jù),以免出現(xiàn)因為數(shù)據(jù)和命令的處理速度慢于發(fā)送速度而導(dǎo)致的數(shù)據(jù)丟失和性能問題赌髓。
緩沖區(qū)超出了設(shè)置的閾值从藤,會發(fā)生緩沖區(qū)溢出,就會丟數(shù)據(jù)锁蠕。如果不給緩沖區(qū)設(shè)置上限呛哟,那么緩沖區(qū)越來越大,一旦耗空Redis實例所在機(jī)器可用內(nèi)存匿沛,會導(dǎo)致Redis掛掉扫责。
緩沖區(qū)兩個場景:
1)、客戶端與服務(wù)器通信時逃呼,用來暫存客戶端發(fā)送的命令數(shù)據(jù)鳖孤,或者是服務(wù)器端返回給客戶端的數(shù)據(jù)結(jié)果
2)、在主從節(jié)點間進(jìn)行數(shù)據(jù)同步時抡笼,用來暫存主節(jié)點接收的寫命令和數(shù)據(jù)苏揣。
2、客戶端輸入和輸出緩沖區(qū)
為了避免客戶端和服務(wù)器端的請求發(fā)送和處理速度不匹配推姻,服務(wù)器端給每個連接的客戶端都設(shè)置了一個輸入緩沖區(qū)和輸出緩沖區(qū)平匈,稱之為客戶端輸入緩沖區(qū)和輸出緩沖區(qū)。
3藏古、如何應(yīng)對輸入緩沖區(qū)溢出增炭?
輸入緩沖區(qū)可能導(dǎo)致溢出的兩種情況:
1)、寫入了 bigkey拧晕,比如一下子寫入了多個百萬級別的集合類型數(shù)據(jù)隙姿;
2)、服務(wù)器端處理請求的速度過慢厂捞,例如输玷,Redis 主線程出現(xiàn)了間歇性阻塞队丝,無法及時處理正常發(fā)送的請求,導(dǎo)致客戶端發(fā)送的請求在緩沖區(qū)越積越多欲鹏。
從如何查看輸入緩沖區(qū)的內(nèi)存使用情況机久,以及如何避免溢出,使用 CLIENT LIST 命令:
CLIENT LIST
id=5 addr=127.0.0.1:50487 fd=9 name= age=4 idle=0 flags=N db=0 sub=0 psub=0 mu
關(guān)注兩類信息:
1)赔嚎、服務(wù)器端連接的客戶端的信息
這個案例展示的是一個客戶端的輸入緩沖區(qū)情況膘盖,如果有多個客戶端,輸出結(jié)果中的 addr 會顯示不同客戶端的 IP 和端口號尽狠。
2)、與輸入緩沖區(qū)相關(guān)的三個參數(shù):
cmd叶圃,表示客戶端最新執(zhí)行的命令袄膏。
qbuf,表示輸入緩沖區(qū)已經(jīng)使用的大小掺冠。
qbuf-free沉馆,表示輸入緩沖區(qū)尚未使用的大小。
總結(jié):如何避免德崭?-------一是把緩沖區(qū)調(diào)大斥黑,二是從數(shù)據(jù)命令的發(fā)送和處理速度入手。
沒有辦法通過參數(shù)調(diào)整輸入緩沖區(qū)的大小眉厨,?Redis 的客戶端輸入緩沖區(qū)大小的上限閾值锌奴,在代碼中就設(shè)定為了 1GB,(Redis服務(wù)器端允許為每個客戶端最多暫存 1GB 的命令和數(shù)據(jù)憾股。)如果再大鹿蜀,可能會占用過多的內(nèi)存資源。
其次從數(shù)據(jù)命令的發(fā)送和處理速度入手服球,也就是前面提到的避免客戶端寫入 bigkey茴恰,以及避免 Redis 主線程阻塞。
4斩熊、如何應(yīng)對輸出緩沖區(qū)溢出往枣?
Redis 的輸出緩沖區(qū)暫存的是 Redis 主線程要返回給客戶端的數(shù)據(jù)。
有OK粉渠、報錯信息分冈、不固定大小的數(shù)據(jù)信息結(jié)果等。
因此霸株,Redis 為每個客戶端設(shè)置的輸出緩沖區(qū)也包括兩部分:
一部分丈秩,是一個大小為 16KB的固定緩沖空間,用來暫存 OK 響應(yīng)和出錯信息淳衙;
另一部分蘑秽,是一個可以動態(tài)增加的緩沖空間饺著,用來暫存大小可變的響應(yīng)結(jié)果。
5肠牲、什么情況下會發(fā)生輸出緩沖區(qū)溢出呢幼衰?
1)、服務(wù)器端返回 bigkey 的大量結(jié)果缀雳;----占用大量內(nèi)存
2)渡嚣、執(zhí)行了 MONITOR 命令;
3)肥印、緩沖區(qū)大小設(shè)置得不合理识椰。
MONITOR 命令是用來監(jiān)測 Redis 執(zhí)行的,執(zhí)行這個命令之后深碱,就會持續(xù)輸出監(jiān)測到的各個命令操作:
MONITOR
OK
1600617456.437129 [0 127.0.0.1:50487] "COMMAND"
1600617477.289667 [0 127.0.0.1:50487] "info" "memory"
MONITOR 的輸出結(jié)果會持續(xù)占用輸出緩沖區(qū)腹鹉,并越占越多,最后的結(jié)果就是發(fā)生溢出敷硅。
輸出緩沖區(qū)大小設(shè)置的問題功咒。和輸入緩沖區(qū)不同,我們可以通過 clientoutput-buffer-limit 配置項绞蹦,來設(shè)置緩沖區(qū)的大小力奋。具體設(shè)置的內(nèi)容包括兩方面:
1)、設(shè)置緩沖區(qū)大小的上限閾值幽七;
2)景殷、設(shè)置輸出緩沖區(qū)持續(xù)寫入數(shù)據(jù)的數(shù)量上限閾值,和持續(xù)寫入數(shù)據(jù)的時間的上限閾值澡屡。
兩類客戶端和 Redis 服務(wù)器端交互滨彻,分別是常規(guī)和 Redis 服務(wù)器端進(jìn)行讀寫命令交互的普通客戶端,以及訂閱了 Redis 頻道的訂閱客戶端挪蹭。
給普通客戶端設(shè)置緩沖區(qū)大小時亭饵,通常可以在 Redis 配置文件中進(jìn)行這樣的設(shè)置:
#normal 表示當(dāng)前設(shè)置的是普通客戶端梁厉,第 1 個 0 設(shè)置的是緩沖區(qū)大小限制辜羊,第 2個 0 和第 3 個 0 分別表示緩沖區(qū)持續(xù)寫入量限制和持續(xù)寫入時間限制,0表示不做限制
client-output-buffer-limit normal 0 0 0
對于訂閱了 Redis 頻道的訂閱客戶端词顾,這么設(shè)置:
#pubsub 參數(shù)表示當(dāng)前是對訂閱客戶端進(jìn)行設(shè)置八秃;8mb 表示輸出緩沖區(qū)的大小上限為 8MB,一旦實際占用的緩沖區(qū)大小要超過 8MB肉盹,服務(wù)器端就會直接關(guān)閉客戶端的連接昔驱;2mb 和 60 表示,如果連續(xù) 60 秒內(nèi)對輸出緩沖區(qū)的寫入量超過 2MB 的話上忍,服務(wù)器端也會關(guān)閉客戶端連接骤肛。
client-output-buffer-limit pubsub 8mb 2mb 60
訂閱客戶端和服務(wù)器間的消息發(fā)送方式纳本,不屬于阻塞式發(fā)送。不過腋颠,如果頻道消息較多的話繁成,也會占用較多的輸出緩沖區(qū)空間。
總結(jié):如何避免輸出緩沖區(qū)溢出淑玫?
避免 bigkey 操作返回大量數(shù)據(jù)結(jié)果巾腕;
避免在線上環(huán)境中持續(xù)使用 MONITOR 命令。
使用 client-output-buffer-limit 設(shè)置合理的緩沖區(qū)大小上限絮蒿,或是緩沖區(qū)連續(xù)寫入時間和寫入量上限尊搬。
6、主從集群中的緩沖區(qū)
主從集群間的數(shù)據(jù)復(fù)制包括全量復(fù)制和增量復(fù)制兩種土涝。全量復(fù)制是同步所有數(shù)據(jù)佛寿,而增量復(fù)制只會把主從庫網(wǎng)絡(luò)斷連期間主庫收到的命令,同步給從庫回铛。
無論在哪種形式的復(fù)制中狗准,為了保證主從節(jié)點的數(shù)據(jù)一致克锣,都會用到緩沖區(qū)茵肃。
7、復(fù)制緩沖區(qū)的溢出問題---復(fù)制緩沖區(qū)
在全量復(fù)制過程中袭祟,主節(jié)點在向從節(jié)點傳輸 RDB 文件的同時验残,會繼續(xù)接收客戶端發(fā)送的寫命令請求。這些寫命令就會先保存在復(fù)制緩沖區(qū)中巾乳,等 RDB 文件傳輸完成后您没,再發(fā)送給從節(jié)點去執(zhí)行。主節(jié)點上會為每個從節(jié)點都維護(hù)一個復(fù)制緩沖區(qū)胆绊,來保證主從節(jié)點間的數(shù)據(jù)同步氨鹏。
所以,如果在全量復(fù)制時压状,從節(jié)點接收和加載 RDB 較慢仆抵,同時主節(jié)點接收到了大量的寫命令,寫命令在復(fù)制緩沖區(qū)中就會越積越多种冬,最終導(dǎo)致溢出镣丑。
主節(jié)點上的復(fù)制緩沖區(qū),本質(zhì)上也是一個用于和從節(jié)點連接的客戶端(我們稱之為從節(jié)點客戶端)娱两,使用的輸出緩沖區(qū)莺匠。復(fù)制緩沖區(qū)一旦發(fā)生溢出,主節(jié)點也會直接關(guān)閉和從節(jié)點進(jìn)行復(fù)制操作的連接十兢,導(dǎo)致全量復(fù)制失敗趣竣。
如何避免摇庙?兩方面
1)、控制主節(jié)點保存的數(shù)據(jù)量大小期贫「遥可以控制主節(jié)點數(shù)據(jù)量在2-4GB,這樣可以讓全量同步執(zhí)行得更快些通砍,避免復(fù)制緩沖區(qū)累積過多命令玛臂。
2)、使用?client-output-buffer-limit 命令配置項封孙,控制復(fù)制緩沖區(qū)大小迹冤。就是主節(jié)點的數(shù)據(jù)量大小、主節(jié)點的寫負(fù)載壓力和主節(jié)點本身的內(nèi)存大小虎忌。
#slave 參數(shù)表明該配置項是針對復(fù)制緩沖區(qū)的泡徙。512mb 代表將緩沖區(qū)大小的上限設(shè)置為 512MB;128mb 和 60 代表的設(shè)置是膜蠢,如果連續(xù) 60 秒內(nèi)的寫入量超過 128MB 的話堪藐,也會觸發(fā)緩沖區(qū)溢出。
config set client-output-buffer-limit slave 512mb 128mb 6
總結(jié)一下:
為了避免復(fù)制緩沖區(qū)累積過多命令造成溢出挑围,引發(fā)全量復(fù)制失敗礁竞,我們可以控制主節(jié)點保存的數(shù)據(jù)量大小,并設(shè)置合理的復(fù)制緩沖區(qū)大小杉辙。同時模捂,我們需要控制從節(jié)點的數(shù)量,來避免主節(jié)點中復(fù)制緩沖區(qū)占用過多內(nèi)存的問題蜘矢。
8狂男、復(fù)制積壓緩沖區(qū)的溢出問題---積壓緩沖區(qū) repl_backlog_buffer
增量復(fù)制時使用
網(wǎng)絡(luò)故障后,主節(jié)點在把接收到的寫命令同步給從節(jié)點時品腹,同時會把這些寫命令寫入復(fù)制積壓緩沖區(qū)岖食。一旦從節(jié)點發(fā)生網(wǎng)絡(luò)閃斷,再次和主節(jié)點恢復(fù)連接后舞吭,從節(jié)點就會從復(fù)制積壓緩沖區(qū)中泡垃,讀取斷連期間主節(jié)點接收到的寫命令,進(jìn)而進(jìn)行增量同步镣典。
首先兔毙,復(fù)制積壓緩沖區(qū)是一個大小有限的環(huán)形緩沖區(qū)。當(dāng)主節(jié)點把復(fù)制積壓緩沖區(qū)寫滿后兄春,會覆蓋緩沖區(qū)中的舊命令數(shù)據(jù)澎剥。如果從節(jié)點還沒有同步這些舊命令數(shù)據(jù),就會造成主從節(jié)點間重新開始執(zhí)行全量復(fù)制。
其次哑姚,為了應(yīng)對復(fù)制積壓緩沖區(qū)的溢出問題祭饭,我們可以調(diào)整復(fù)制積壓緩沖區(qū)的大小,也就是設(shè)置 repl_backlog_size 這個參數(shù)的值叙量。
哈哈倡蝙,我沒記錯,是二倍關(guān)系?repl_backlog_size = 緩沖空間大小 * 2
9绞佩、小結(jié)
1)寺鸥、Redis 中使用的緩沖區(qū)。使用緩沖區(qū)以后品山,當(dāng)命令數(shù)據(jù)的接收方處理速度跟不上發(fā)送方的發(fā)送速度時胆建,緩沖區(qū)可以避免命令數(shù)據(jù)的丟失。
2)肘交、按照緩沖區(qū)的用途笆载,例如是用于客戶端通信還是用于主從節(jié)點復(fù)制,把緩沖區(qū)分成了客戶端的輸入和輸出緩沖區(qū)涯呻,以及主從集群中主節(jié)點上的復(fù)制緩沖區(qū)和復(fù)制積壓緩沖區(qū)凉驻。
3)、緩沖區(qū)溢出對 Redis 的影響的角度复罐,再把這四個緩沖區(qū)分成兩類做個總結(jié):
緩沖區(qū)溢出導(dǎo)致網(wǎng)絡(luò)連接關(guān)閉:普通客戶端涝登、訂閱客戶端,以及從節(jié)點客戶端市栗,它們使用的緩沖區(qū)缀拭,本質(zhì)上都是 Redis 客戶端和服務(wù)器端之間咳短,或是主從節(jié)點之間為了傳輸命令數(shù)據(jù)而維護(hù)的填帽。這些緩沖區(qū)一旦發(fā)生溢出,處理機(jī)制都是直接把客戶端和服務(wù)器端的連接咙好,或是主從節(jié)點間的連接關(guān)閉篡腌。網(wǎng)絡(luò)連接關(guān)閉造成的直接影響,就是業(yè)務(wù)程序無法讀寫 Redis勾效,或者是主從節(jié)點全量同步失敗嘹悼,需要重新執(zhí)行。
緩沖區(qū)溢出導(dǎo)致命令數(shù)據(jù)丟失:主節(jié)點上的復(fù)制積壓緩沖區(qū)屬于環(huán)形緩沖區(qū)层宫,一旦發(fā)生溢出杨伙,新寫入的命令數(shù)據(jù)就會覆蓋舊的命令數(shù)據(jù),導(dǎo)致舊命令數(shù)據(jù)的丟失萌腿,進(jìn)而導(dǎo)致主從節(jié)點重新進(jìn)行全量復(fù)制限匣。
4)、從本質(zhì)上看毁菱,緩沖區(qū)溢出無非就是三個原因:命令數(shù)據(jù)發(fā)送過快過大米死;命令數(shù)據(jù)處理較慢锌历;緩沖區(qū)空間過小。
5)峦筒、應(yīng)對策略
a究西、針對命令數(shù)據(jù)發(fā)送過快過大的問題,對于普通客戶端來說可以避免 bigkey物喷,而對于復(fù)制緩沖區(qū)來說卤材,就是避免過大的 RDB 文件。
b峦失、針對命令數(shù)據(jù)處理較慢的問題商膊,解決方案就是減少 Redis 主線程上的阻塞操作,例如使用異步的刪除操作宠进。
c晕拆、針對緩沖區(qū)空間過小的問題,解決方案就是使用 client-output-buffer-limit 配置項設(shè)置合理的輸出緩沖區(qū)材蹬、復(fù)制緩沖區(qū)和復(fù)制積壓緩沖區(qū)大小实幕。當(dāng)然,不要忘了堤器,輸入緩沖區(qū)的大小默認(rèn)是固定的昆庇,我們無法通過配置來修改它,除非直接去修改 Redis 源碼闸溃。