機制詳解:輸入輸出與復(fù)制緩沖區(qū)調(diào)優(yōu)實戰(zhàn))
1. 從一次緩存雪崩說起Redis緩沖區(qū)到底在緩沖什么很多人第一次接觸Redis的“緩沖區(qū)”是在一次線上告警之后。某個晚上監(jiān)控突然顯示Redis內(nèi)存暴漲緊接著大量請求超時業(yè)務(wù)側(cè)開始報錯。排查下來發(fā)現(xiàn)問題并不在Redis本身而在于客戶端輸出緩沖區(qū)堆積了大量數(shù)據(jù)——某個消費者處理速度跟不上Redis卻還在拼命往里塞數(shù)據(jù)最終把內(nèi)存撐爆了。這個場景里提到的“緩沖區(qū)”就是Redis里一個容易被忽視、但關(guān)鍵時刻能救命的設(shè)計。它不像String、Hash、List這些數(shù)據(jù)類型那樣天天被掛在嘴邊但只要你用Redis做消息隊列、做發(fā)布訂閱、做數(shù)據(jù)同步就一定會和它打交道。所謂緩沖區(qū)本質(zhì)上是Redis在內(nèi)存中劃出的一塊臨時存儲區(qū)域用來協(xié)調(diào)“生產(chǎn)速度”和“消費速度”之間的不平衡。生產(chǎn)者寫得快消費者讀得慢中間就需要一個地方先把數(shù)據(jù)存起來等消費者慢慢取。這個“中間的地方”就是緩沖區(qū)。Redis里的緩沖區(qū)不是一個單一概念它至少包含三類客戶端輸入緩沖區(qū)、客戶端輸出緩沖區(qū)、復(fù)制緩沖區(qū)。這三者服務(wù)的目標不同觸發(fā)條件不同出問題時的表現(xiàn)也完全不同。很多人把它們混為一談結(jié)果排查問題時方向就跑偏了。這篇文章會從實際使用角度出發(fā)把這三類緩沖區(qū)的機制、配置、監(jiān)控和調(diào)優(yōu)講清楚。不管你是剛接觸Redis的新手還是已經(jīng)用過一段時間但沒深究過緩沖區(qū)的開發(fā)者都能從中找到可以直接落地的操作方法和避坑經(jīng)驗。2. 客戶端輸入緩沖區(qū)那條容易被忽略的“接收管道”2.1 輸入緩沖區(qū)的工作機制與內(nèi)存上限客戶端輸入緩沖區(qū)英文叫query buffer是Redis用來暫存客戶端發(fā)過來的命令的地方。當客戶端通過TCP連接把命令發(fā)給Redis時Redis不會立刻執(zhí)行而是先把命令讀進輸入緩沖區(qū)然后由命令解析器逐條取出執(zhí)行。這個緩沖區(qū)的大小是動態(tài)變化的。如果客戶端發(fā)送的命令很大比如一個包含幾萬個元素的批量寫入命令輸入緩沖區(qū)就會臨時膨脹。Redis默認對輸入緩沖區(qū)沒有硬性大小限制但它受client-query-buffer-limit參數(shù)約束默認值是1GB。# 查看當前輸入緩沖區(qū)限制 redis-cli config get client-query-buffer-limit # 輸出client-query-buffer-limit 1073741824這個1GB的限制意味著如果某個客戶端發(fā)送了一個超過1GB的命令Redis會直接斷開這個連接并在日志里記錄一條警告。這個設(shè)計是為了防止單個客戶端用超大命令把Redis內(nèi)存打滿。2.2 什么情況下輸入緩沖區(qū)會出問題最常見的輸入緩沖區(qū)問題來自“大key”操作。比如有人用DEL命令刪除一個包含幾百萬個元素的Hash或者用HGETALL一次性拉取一個巨大的Hash。這些命令本身可能不大但Redis在執(zhí)行時產(chǎn)生的中間數(shù)據(jù)會占用大量內(nèi)存。更隱蔽的情況是客戶端在短時間內(nèi)發(fā)送了大量命令而Redis處理速度跟不上。這時候輸入緩沖區(qū)會持續(xù)增長直到觸及上限。一旦觸及上限Redis會強制斷開連接客戶端會收到一個“connection reset by peer”的錯誤。我遇到過這樣一個案例某業(yè)務(wù)用Redis做批量數(shù)據(jù)導(dǎo)入客戶端一次性發(fā)送了包含50萬條SET命令的pipeline。雖然每條命令都不大但50萬條命令疊加起來輸入緩沖區(qū)瞬間超過了1GBRedis直接斷開了連接。后來改成每批1萬條分50批發(fā)送問題就解決了。提示使用pipeline時不要一次性塞入過多命令。建議每批控制在5000到10000條之間具體數(shù)量根據(jù)命令大小調(diào)整。2.3 監(jiān)控輸入緩沖區(qū)的實用方法Redis提供了CLIENT LIST命令可以查看每個客戶端的輸入緩沖區(qū)使用情況。輸出里的qbuf字段表示輸入緩沖區(qū)當前大小qbuf-free表示剩余空間。redis-cli client list # 輸出示例 # id3 addr127.0.0.1:52344 fd8 name age0 idle0 flagsN db0 sub0 psub0 multi-1 qbuf26 qbuf-free20474 obl0 oll0 omem0 eventsr cmdclient如果發(fā)現(xiàn)某個客戶端的qbuf持續(xù)增長說明這個客戶端發(fā)送命令的速度超過了Redis的處理速度。這時候可以考慮在客戶端側(cè)做限流或者優(yōu)化命令結(jié)構(gòu)減少單次發(fā)送的數(shù)據(jù)量。另外可以通過INFO clients查看整體情況redis-cli info clients # 輸出示例 # connected_clients:10 # client_recent_max_input_buffer:20480 # client_recent_max_output_buffer:0 # blocked_clients:0client_recent_max_input_buffer表示最近一段時間內(nèi)輸入緩沖區(qū)的最大使用量。如果這個值經(jīng)常接近1GB就需要警惕了。3. 客戶端輸出緩沖區(qū)消費者太慢時的那顆定時炸彈3.1 輸出緩沖區(qū)的分類與觸發(fā)條件輸出緩沖區(qū)是Redis用來暫存“準備發(fā)給客戶端但還沒發(fā)出去”的數(shù)據(jù)的地方。它比輸入緩沖區(qū)更容易出問題因為輸出緩沖區(qū)的增長往往是被動的——Redis無法控制客戶端什么時候來讀數(shù)據(jù)。輸出緩沖區(qū)分為三類對應(yīng)不同的客戶端類型類型對應(yīng)客戶端默認限制說明normal普通客戶端0不限制執(zhí)行常規(guī)命令的客戶端slave從節(jié)點客戶端256MB主從復(fù)制時從節(jié)點連接pubsub發(fā)布訂閱客戶端32MB訂閱了頻道或模式的客戶端普通客戶端的輸出緩沖區(qū)默認不限制這是最危險的地方。如果某個客戶端執(zhí)行了HGETALL拉取大量數(shù)據(jù)但網(wǎng)絡(luò)很慢或者客戶端處理很慢數(shù)據(jù)就會堆積在輸出緩沖區(qū)里直到把Redis內(nèi)存撐爆。從節(jié)點和發(fā)布訂閱客戶端的輸出緩沖區(qū)有默認限制超過限制后Redis會強制斷開連接。這個設(shè)計是為了保護Redis本身避免被慢消費者拖垮。3.2 一個真實的內(nèi)存暴漲排查過程某次線上告警Redis實例內(nèi)存從2GB突然漲到8GB持續(xù)了大約10分鐘后回落。排查過程如下第一步查看INFO memory確認內(nèi)存確實異常增長且used_memory_peak遠高于正常水平。第二步查看INFO clients發(fā)現(xiàn)client_recent_max_output_buffer數(shù)值很大說明有客戶端的輸出緩沖區(qū)在膨脹。第三步執(zhí)行CLIENT LIST按omem字段排序找到輸出緩沖區(qū)占用最大的客戶端。發(fā)現(xiàn)是一個訂閱了某個頻道的客戶端omem達到了200MB。第四步檢查這個客戶端的消費邏輯發(fā)現(xiàn)它在收到消息后做了一段耗時的數(shù)據(jù)庫寫入操作導(dǎo)致消息在輸出緩沖區(qū)里越積越多。第五步確認這個客戶端訂閱的頻道消息量很大生產(chǎn)端每秒推送幾千條消息而消費端每秒只能處理幾百條。問題根因清楚了生產(chǎn)速度遠大于消費速度輸出緩沖區(qū)成了“堰塞湖”。解決方案有兩個方向一是限制生產(chǎn)端的推送速度二是在消費端做異步處理先把消息存到本地隊列再慢慢消費。3.3 輸出緩沖區(qū)的配置與調(diào)優(yōu)針對不同類型的客戶端可以通過以下參數(shù)調(diào)整輸出緩沖區(qū)限制# 普通客戶端輸出緩沖區(qū)限制0表示不限制單位是字節(jié) redis-cli config set client-output-buffer-limit normal 0 0 0 # 從節(jié)點輸出緩沖區(qū)限制硬限制256MB軟限制64MB/60秒 redis-cli config set client-output-buffer-limit slave 268435456 67108864 60 # 發(fā)布訂閱客戶端輸出緩沖區(qū)限制硬限制32MB軟限制8MB/60秒 redis-cli config set client-output-buffer-limit pubsub 33554432 8388608 60硬限制和軟限制的區(qū)別硬限制是“一旦超過就立刻斷開”軟限制是“超過后持續(xù)N秒才斷開”。軟限制給了客戶端一個緩沖期避免因為瞬時峰值被誤殺。對于普通客戶端我建議不要設(shè)置為0不限制而是設(shè)置一個合理的硬限制比如512MB。這樣即使某個客戶端出了問題也不會把整個Redis實例拖垮。注意修改client-output-buffer-limit后新連接會立即生效但已有連接需要重新建立才會應(yīng)用新配置。3.4 發(fā)布訂閱場景下的緩沖區(qū)陷阱發(fā)布訂閱是輸出緩沖區(qū)最容易出問題的場景。因為發(fā)布訂閱是“推模式”Redis會主動把消息推給訂閱者不管訂閱者能不能處理得過來。假設(shè)一個頻道每秒產(chǎn)生1萬條消息每條消息1KB那么每秒就是10MB的數(shù)據(jù)。如果訂閱者每秒只能處理1000條那么每秒就有9MB的數(shù)據(jù)堆積在輸出緩沖區(qū)里。32MB的默認限制不到4秒就會被突破然后Redis就會斷開這個訂閱者。更麻煩的是斷開后訂閱者如果自動重連又會重新訂閱然后再次被斷開形成“斷開-重連-斷開”的循環(huán)。這個循環(huán)會消耗大量CPU和網(wǎng)絡(luò)資源。解決這個問題的思路有幾個在訂閱者側(cè)做限流控制消息處理速度確保不會堆積。使用Redis Stream代替發(fā)布訂閱Stream支持消費者組和ACK機制可以更好地控制消費進度。如果消息量確實很大考慮用消息隊列中間件替代Redis的發(fā)布訂閱功能。4. 復(fù)制緩沖區(qū)主從同步背后的“蓄水池”4.1 復(fù)制緩沖區(qū)的工作原理復(fù)制緩沖區(qū)是主節(jié)點用來暫存“待發(fā)送給從節(jié)點”的寫命令的地方。當主節(jié)點執(zhí)行一個寫命令后除了寫入自己的數(shù)據(jù)集還會把命令寫入復(fù)制緩沖區(qū)然后由復(fù)制線程發(fā)送給各個從節(jié)點。復(fù)制緩沖區(qū)分為兩部分固定緩沖區(qū)和動態(tài)緩沖區(qū)。固定緩沖區(qū)是一塊固定大小的內(nèi)存默認1MB。當主從連接正常時寫命令會先寫入固定緩沖區(qū)然后盡快發(fā)送給從節(jié)點。如果從節(jié)點網(wǎng)絡(luò)延遲較大固定緩沖區(qū)滿了后續(xù)命令就會寫入動態(tài)緩沖區(qū)。動態(tài)緩沖區(qū)是按需分配的可以動態(tài)擴展。如果從節(jié)點長時間無法接收數(shù)據(jù)動態(tài)緩沖區(qū)會持續(xù)增長直到觸及client-output-buffer-limit slave的限制然后主節(jié)點會斷開這個從節(jié)點。4.2 主從延遲導(dǎo)致的緩沖區(qū)膨脹主從延遲是復(fù)制緩沖區(qū)膨脹的常見原因。當從節(jié)點處理速度跟不上主節(jié)點時復(fù)制緩沖區(qū)就會堆積。可以通過INFO replication查看主從延遲情況redis-cli info replication # 輸出示例 # role:master # connected_slaves:1 # slave0:ip127.0.0.1,port6380,stateonline,offset123456,lag0 # master_repl_offset:123456 # repl_backlog_active:1 # repl_backlog_size:1048576 # repl_backlog_first_byte_offset:1 # repl_backlog_histlen:123456lag字段表示從節(jié)點的延遲秒數(shù)。如果這個值持續(xù)大于0說明從節(jié)點處理不過來。repl_backlog_size是復(fù)制積壓緩沖區(qū)的大小默認1MB。如果從節(jié)點斷開后重連主節(jié)點會嘗試從積壓緩沖區(qū)里補發(fā)數(shù)據(jù)。如果積壓緩沖區(qū)不夠大就需要做全量同步。4.3 復(fù)制緩沖區(qū)的調(diào)優(yōu)參數(shù)# 設(shè)置復(fù)制積壓緩沖區(qū)大小默認1MB redis-cli config set repl-backlog-size 64mb # 設(shè)置從節(jié)點輸出緩沖區(qū)限制 redis-cli config set client-output-buffer-limit slave 536870912 134217728 60repl-backlog-size的設(shè)置需要根據(jù)實際情況調(diào)整。如果主節(jié)點寫入量很大從節(jié)點經(jīng)常斷開重連建議把這個值調(diào)大比如64MB或128MB。這樣可以避免頻繁的全量同步。從節(jié)點輸出緩沖區(qū)的硬限制建議設(shè)置為512MB軟限制設(shè)置為128MB/60秒。這樣既能容忍一定的網(wǎng)絡(luò)抖動又不會讓緩沖區(qū)無限增長。4.4 全量同步與增量同步的緩沖區(qū)差異全量同步時主節(jié)點會生成RDB文件發(fā)送給從節(jié)點。這個過程中主節(jié)點會把新產(chǎn)生的寫命令寫入復(fù)制緩沖區(qū)等RDB發(fā)送完成后再把緩沖區(qū)里的命令發(fā)給從節(jié)點。如果RDB文件很大傳輸時間很長復(fù)制緩沖區(qū)就會堆積大量命令。如果堆積超過限制從節(jié)點會被斷開然后重新嘗試全量同步形成惡性循環(huán)。增量同步時主節(jié)點只需要把積壓緩沖區(qū)里的命令發(fā)給從節(jié)點數(shù)據(jù)量小得多緩沖區(qū)壓力也小。所以保持主從連接穩(wěn)定、避免頻繁斷開是減少復(fù)制緩沖區(qū)壓力的關(guān)鍵。5. 緩沖區(qū)監(jiān)控與告警把問題扼殺在爆發(fā)之前5.1 需要重點監(jiān)控的指標緩沖區(qū)問題往往不是突然出現(xiàn)的而是有一個漸進的過程。通過監(jiān)控以下指標可以在問題爆發(fā)前發(fā)現(xiàn)苗頭指標來源告警閾值建議說明client_recent_max_input_bufferINFO clients 100MB輸入緩沖區(qū)最大值client_recent_max_output_bufferINFO clients 50MB輸出緩沖區(qū)最大值blocked_clientsINFO clients 0 持續(xù)5分鐘被阻塞的客戶端數(shù)mem_fragmentation_ratioINFO memory 1.5內(nèi)存碎片率used_memory_peakINFO memory接近maxmemory內(nèi)存峰值slave lagINFO replication 10秒從節(jié)點延遲這些指標可以通過Redis的INFO命令獲取然后接入監(jiān)控系統(tǒng)。建議設(shè)置兩級告警警告級別和嚴重級別。警告級別用于提前介入嚴重級別用于緊急處理。5.2 用CLIENT LIST做實時排查當告警觸發(fā)后第一步應(yīng)該是執(zhí)行CLIENT LIST查看當前所有客戶端的緩沖區(qū)使用情況。# 按輸出緩沖區(qū)大小排序找出占用最大的客戶端 redis-cli client list | awk {print $0} | sort -t -k7 -rn | head -10更精確的做法是用--bigkeys或者寫腳本解析CLIENT LIST輸出提取qbuf、qbuf-free、omem等字段按大小排序。import redis r redis.Redis(hostlocalhost, port6379) clients r.client_list() # 按輸出緩沖區(qū)內(nèi)存排序 sorted_clients sorted(clients, keylambda x: int(x[omem]), reverseTrue) for c in sorted_clients[:10]: print(faddr{c[addr]} name{c[name]} omem{c[omem]} qbuf{c[qbuf]} cmd{c[cmd]})這個腳本可以快速定位到問題客戶端。拿到客戶端地址后就可以去對應(yīng)的業(yè)務(wù)側(cè)排查消費邏輯了。5.3 慢查詢?nèi)罩九c緩沖區(qū)的關(guān)聯(lián)慢查詢?nèi)罩居涗浀氖菆?zhí)行時間超過閾值的命令。雖然慢查詢本身不直接等于緩沖區(qū)問題但兩者經(jīng)常同時出現(xiàn)。比如一個HGETALL命令執(zhí)行了500毫秒返回了10MB數(shù)據(jù)。這500毫秒內(nèi)數(shù)據(jù)會先寫入輸出緩沖區(qū)然后才發(fā)送給客戶端。如果客戶端網(wǎng)絡(luò)慢這10MB數(shù)據(jù)就會在輸出緩沖區(qū)里停留更久。所以分析慢查詢?nèi)罩緯r不僅要關(guān)注執(zhí)行時間還要關(guān)注返回數(shù)據(jù)量。返回數(shù)據(jù)量大的命令即使執(zhí)行時間不長也可能導(dǎo)致輸出緩沖區(qū)膨脹。# 查看慢查詢?nèi)罩?redis-cli slowlog get 10 # 輸出示例 # 1) 1) (integer) 14 # 2) (integer) 1634567890 # 3) (integer) 500000 # 4) 1) HGETALL # 2) big_hash_key # 5) 127.0.0.1:52344 # 6) 慢查詢?nèi)罩纠锏牡?項是命令參數(shù)第5項是客戶端地址。如果發(fā)現(xiàn)某個客戶端頻繁出現(xiàn)在慢查詢?nèi)罩纠锴颐罘祷財?shù)據(jù)量大就需要重點檢查這個客戶端的輸出緩沖區(qū)。6. 實戰(zhàn)調(diào)優(yōu)不同業(yè)務(wù)場景下的緩沖區(qū)配置策略6.1 緩存場景普通客戶端緩沖區(qū)配置緩存場景下客戶端通常是執(zhí)行GET、SET這類簡單命令返回數(shù)據(jù)量小緩沖區(qū)壓力不大。但也不能完全不管因為總會有意外情況。建議配置# 普通客戶端輸出緩沖區(qū)硬限制256MB軟限制64MB/60秒 redis-cli config set client-output-buffer-limit normal 268435456 67108864 60 # 輸入緩沖區(qū)限制保持默認1GB即可這個配置下單個客戶端最多占用256MB輸出緩沖區(qū)。即使出問題也不會把整個實例拖垮。6.2 消息隊列場景發(fā)布訂閱緩沖區(qū)配置用發(fā)布訂閱做消息隊列時緩沖區(qū)配置需要更謹慎。因為發(fā)布訂閱是推模式消費端一旦跟不上緩沖區(qū)就會快速膨脹。建議配置# 發(fā)布訂閱客戶端輸出緩沖區(qū)硬限制64MB軟限制16MB/30秒 redis-cli config set client-output-buffer-limit pubsub 67108864 16777216 30同時在消費端做限流和異步處理。收到消息后先寫入本地內(nèi)存隊列然后由獨立的線程池慢慢消費。這樣即使Redis推送速度很快消費端也不會因為處理慢而導(dǎo)致緩沖區(qū)堆積。如果消息量確實很大建議改用Redis Stream。Stream支持消費者組可以控制每個消費者的消費進度不會因為單個消費者慢而影響整個隊列。6.3 主從復(fù)制場景復(fù)制緩沖區(qū)配置主從復(fù)制場景下復(fù)制緩沖區(qū)的配置直接影響主從同步的穩(wěn)定性。建議配置# 復(fù)制積壓緩沖區(qū)大小64MB redis-cli config set repl-backlog-size 64mb # 從節(jié)點輸出緩沖區(qū)硬限制512MB軟限制128MB/60秒 redis-cli config set client-output-buffer-limit slave 536870912 134217728 60如果主節(jié)點寫入量很大比如每秒幾十MB建議把repl-backlog-size調(diào)到128MB甚至256MB。這樣可以容忍從節(jié)點更長時間的斷開避免全量同步。另外建議開啟repl-backlog-ttl設(shè)置一個合理的過期時間比如3600秒。這樣當所有從節(jié)點都斷開后積壓緩沖區(qū)會在1小時后自動釋放不會一直占用內(nèi)存。6.4 大key場景如何避免緩沖區(qū)被單個命令打爆大key是緩沖區(qū)問題的常見誘因。一個包含幾百萬元素的Hash執(zhí)行HGETALL會返回幾十MB數(shù)據(jù)直接寫入輸出緩沖區(qū)。避免大key緩沖區(qū)問題的策略拆分大key。把一個包含100萬元素的Hash拆成100個包含1萬元素的Hash用HGETALL時只拉取需要的那部分。使用HSCAN代替HGETALL。HSCAN是漸進式遍歷每次只返回少量數(shù)據(jù)不會一次性把整個Hash拉出來。在客戶端做分頁。比如用HMGET每次只取100個字段分多次取完。# 不推薦一次性拉取整個Hash HGETALL big_hash_key # 推薦用HSCAN漸進式遍歷 HSCAN big_hash_key 0 COUNT 100HSCAN的COUNT參數(shù)控制每次返回的元素數(shù)量默認是10。可以根據(jù)實際情況調(diào)整比如設(shè)置為100或1000。這樣每次只返回少量數(shù)據(jù)輸出緩沖區(qū)不會瞬間膨脹。7. 幾個容易踩的坑和我的個人經(jīng)驗7.1 不要忽略普通客戶端的輸出緩沖區(qū)限制很多人只關(guān)注從節(jié)點和發(fā)布訂閱的緩沖區(qū)限制覺得普通客戶端不會出問題。但實際上普通客戶端的輸出緩沖區(qū)默認不限制一旦出問題就是大問題。我見過一個案例某業(yè)務(wù)用LRANGE拉取一個包含100萬元素的List每次拉取10萬個元素??蛻舳司W(wǎng)絡(luò)帶寬有限10萬個元素的數(shù)據(jù)在輸出緩沖區(qū)里堆積最終把Redis內(nèi)存撐爆了。如果提前設(shè)置了普通客戶端的輸出緩沖區(qū)限制Redis會在這個客戶端占用過多內(nèi)存時主動斷開它保護整個實例。7.2 軟限制比硬限制更實用硬限制是“超過就殺”軟限制是“超過后持續(xù)N秒才殺”。在實際使用中軟限制往往更實用。因為網(wǎng)絡(luò)抖動是常態(tài)瞬時峰值不應(yīng)該導(dǎo)致連接被斷開。比如發(fā)布訂閱場景設(shè)置硬限制64MB、軟限制16MB/30秒。如果某個瞬間消息量突增輸出緩沖區(qū)從10MB漲到20MB超過了軟限制但沒超過硬限制。如果30秒內(nèi)回落到16MB以下連接就不會被斷開。如果持續(xù)超過16MB超過30秒才會被斷開。這個設(shè)計給了系統(tǒng)一個緩沖期避免因為瞬時峰值誤殺正常連接。7.3 定期檢查緩沖區(qū)配置是否生效修改緩沖區(qū)配置后一定要驗證是否生效??梢酝ㄟ^CONFIG GET查看當前配置redis-cli config get client-output-buffer-limit # 輸出示例 # 1) client-output-buffer-limit # 2) normal 268435456 67108864 60 slave 536870912 134217728 60 pubsub 67108864 16777216 30如果配置沒有生效可能是修改方式不對。比如用CONFIG SET修改的配置在Redis重啟后會丟失需要寫入配置文件才能持久化。# 寫入配置文件 redis-cli config rewrite這個命令會把當前配置寫入Redis的配置文件確保重啟后配置不丟失。7.4 緩沖區(qū)問題往往不是Redis的問題最后分享一個心得緩沖區(qū)問題表面上出在Redis但根因往往在客戶端。消費速度慢、網(wǎng)絡(luò)帶寬不足、命令使用不當這些才是緩沖區(qū)膨脹的真正原因。所以排查緩沖區(qū)問題時不要只盯著Redis看要去客戶端側(cè)找原因。看看消費邏輯是不是有性能瓶頸網(wǎng)絡(luò)是不是有丟包或延遲命令是不是用錯了。解決了客戶端的問題緩沖區(qū)問題自然就消失了。我在實際使用中發(fā)現(xiàn)大部分緩沖區(qū)告警都可以通過優(yōu)化客戶端邏輯來解決。真正需要調(diào)整Redis配置的情況反而不多。所以遇到緩沖區(qū)問題時先查客戶端再查Redis這個順序能幫你更快定位問題。