網(wǎng)站首頁 編程語言 正文
Redis緩沖區(qū)機制
Redis中的緩沖區(qū)機制就是為了平衡客戶端發(fā)送命令和服務端處理命令的速度差異,如果客戶端寫入過快或者服務端讀取過慢這就會導致緩沖區(qū)溢出,緩沖區(qū)一旦溢出將引發(fā)一系列的性能問題,下面我們詳細聊聊。
客戶端緩沖機制
Redis為每一個客戶端都分配了一個輸入緩沖區(qū)和輸出緩沖區(qū),輸入緩沖區(qū)會把客戶端的請求命令暫存起來,Redis主線程會從緩沖區(qū)中獲取命令,當Redis處理完命令后會將結果寫入到輸出緩沖區(qū)中,通過輸出緩沖區(qū)返回給客戶端,如下所示
應對輸入緩沖區(qū)溢出
輸入緩沖區(qū)溢出一般就是兩種情況
- 寫入數(shù)據(jù)過快,或者寫入bigkey的數(shù)據(jù)占滿數(shù)據(jù)緩沖區(qū)。
- 服務端處理數(shù)據(jù)過慢,一般是主線程被阻塞無法正常響應客戶端請求。
查看輸入緩沖區(qū)信息
我們可以采用client list
查看輸入緩沖區(qū)的具體信息
127.0.0.1:6379> client list id=13 addr=127.0.0.1:50484 fd=7 name= age=1136 idle=1 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=32742 obl=0 oll=0 omem=0 events=r cmd=client user=default id=14 addr=127.0.0.1:50486 fd=8 name= age=1114 idle=6 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=client user=default
每連接上一個客戶端就會多一條輸入緩沖區(qū)信息,上面命令是我本地連接兩個客戶端的結果,我們查看緩沖區(qū)主要關注內存相關的兩個參數(shù)
- qbuf:緩沖區(qū)已經(jīng)使用的長度(字節(jié)為單位,0表示沒有分配緩沖區(qū))。
- qbuf-free:緩沖區(qū)剩余空閑空間(字節(jié)為單位),上面一個客戶端的qbuf=26,空閑緩沖區(qū)qbuf-free=32742,那么分配內存總大小為26+32742=32768字節(jié)也就是32KB。
如果輸入緩沖區(qū)信息中的qbuf-free很小并且qbuf很大時就需要注意了,這時輸入緩沖區(qū)可能已經(jīng)快溢出了,如果此時還有大量請求寫入輸入緩沖區(qū),Redis的解決辦法就是關閉和這個客戶端的連接,那么業(yè)務數(shù)據(jù)將無法正常存取。
而且還有一個問題就是輸入緩沖區(qū)是每一個客戶端都會存在,那么當所有客戶端的輸入緩沖區(qū)內存總和超過了maxmemory配置,那么將引發(fā)內存淘汰,部分淘汰的數(shù)據(jù)再次訪問需要從后臺數(shù)據(jù)庫獲取,獲取的耗時肯定比Redis直接讀取慢的多,所以這也是Redis產(chǎn)生延遲的一個原因。
如何解決輸入緩沖區(qū)溢出
輸入緩沖區(qū)溢出本質就是緩沖區(qū)的容量不夠,所以第一個思路就是擴大輸入緩沖區(qū)的大小,很不幸Redis沒有提供給我們修改輸入緩沖區(qū)大小的配置,Redis要求每個客戶端的輸入緩沖區(qū)最大不能超過1G,注意是每個客戶端!!!,如果客戶端的輸入緩沖區(qū)超過一個1G將關閉客戶端連接,所以這個是行不通的。
那就只能從客戶端發(fā)送數(shù)據(jù)的大小以及服務端處理命令的速度,客戶端需要避免bigkey的寫入bigkey的劣勢太多一般都需要拆分,第二服務端的命令處理速度這個一般依賴于主線程是否阻塞,需要盡量的避免一些阻塞操作如AOF文件重寫,鍵值刪除,fork線程等等。
應對輸出緩沖區(qū)溢出
對于服務端而言,客戶端的輸入信息通常都是不可預測的,但是輸出信息大多可以預測,如Set命令返回信息只是一個簡單的OK,又如一些報錯信息,Redis為這些不變的返回信息分配了16KB的固定緩沖空間,也就是說輸出緩沖區(qū)分為兩個部分一部分是輸出緩沖區(qū)固定返回信息,一部分是可變的返回信息。
輸出緩沖區(qū)溢出分為三種情況
- 輸出bigkey等容量大的鍵值。
- 客戶端執(zhí)行Monitor命令,監(jiān)控Redis執(zhí)行。
- 緩沖區(qū)設置不合理。
bigkey是老生常談的一個問題,當服務端輸出一個bigkey或者keys這類命令,對輸出緩沖區(qū)的考驗是非常大的,因為查詢的一瞬間會占據(jù)輸入緩沖區(qū)大量的內存空間。
Monitor命令的執(zhí)行
Monitor命令一般是一個debug命令,用來監(jiān)控Redis的具體執(zhí)行情況,能夠返回服務器處理的每一個命令。
127.0.0.1:6379> monitor OK 1652184977.609761 [0 127.0.0.1:50484] "get" "name" 1652185391.529292 [0 127.0.0.1:50484] "set" "test" "lisi" ......
一直運行monitor將一直占據(jù)輸出緩沖區(qū),也就是說占據(jù)時間越長,越容易造成輸出緩沖區(qū)的溢出,所以Monitor命令僅僅只適用于調試環(huán)境,不能在生產(chǎn)上執(zhí)行這些命令。
輸出緩沖區(qū)設置不合理
輸入緩沖區(qū)的大小不能設置,但是輸出緩沖區(qū)的是可以設置的我們可以通過配置項client-output-buffer-limit
來設置,設置的內容就是兩部分
- 緩沖區(qū)的內存大小,當超過緩沖區(qū)配置的大小,服務端會關閉和客戶端的連接。
- 持續(xù)寫入的時間限制和持續(xù)寫入的容量限制,當超過持續(xù)寫入時間限制和容量限制,服務端也會強制關閉和客戶端的連接。
客戶端種類
在聊緩沖區(qū)配置時,我們需要先了解下客戶端的種類,本文中強調的客戶端并不是單純指通過命令./redis-cli -c -h 127.0.0.1 -p 6379
去連接Redis服務器這類客戶端稱為常規(guī)客戶端,我們還有通過消息訂閱Redis頻道的客戶端,還有一種最為特殊的主從同步,從節(jié)點也是一個特殊的客戶端稱為從節(jié)點客戶端。
配置項client-output-buffer-limit
也是針對這三種,給出了不一樣的配置,如下所示
## 普通客戶端配置 client-output-buffer-limit normal 0 0 0 ## 從節(jié)點客戶端配置 client-output-buffer-limit replica 256mb 64mb 60 ## 消息訂閱頻道的客戶端 client-output-buffer-limit pubsub 32mb 8mb 60 ######################配置解釋###################### ## 第一個參數(shù):代表分配給客戶端的緩存大小,為0代表沒有限制 ## 第二個參數(shù):表示持續(xù)寫入的最大內存,為0代表沒有限制 ## 第三個參數(shù):表示持續(xù)寫入的最長時間,為0代表沒有限制
普通客戶端設置
普通客戶端就是傳輸?shù)囊恍┢胀ǖ闹噶睿粋€指令發(fā)送完需要等待其返回后才會發(fā)送下一個指令,也就是說只要不是返回的bigkey數(shù)據(jù),占用輸出緩沖區(qū)的內存就極少,能夠立即發(fā)送給客戶端響應,所以一般正常客戶端默認配置都是0,也就是不限制。
消息訂閱頻道客戶端
當訂閱頻道產(chǎn)生消息后,會將消息通過輸出緩沖區(qū)發(fā)送給客戶端,這種屬于非阻塞的方式,一瞬間可能有多個指令到達,所以需要指定緩沖區(qū)大小。
如何解決輸出緩沖區(qū)溢出
到這里其實我們已經(jīng)能夠得到輸出緩沖區(qū)溢出的解決方案了
- bigkey應當避免使用。
- Monitor命令只在調試的時候使用,不能應用到生產(chǎn)。
- 合理設置輸出緩沖區(qū)上限、持續(xù)寫入時間上限以及持續(xù)寫入內存容量上限。
主從集群中的緩沖區(qū)
除了輸入緩沖區(qū)和輸出緩沖區(qū)外在主從集群場景下還存在兩種緩沖區(qū),我們稱為復制緩沖區(qū)和復制積壓緩沖區(qū),這兩個緩沖區(qū)的溢出和輸入輸出緩沖區(qū)稍有不同。
復制緩沖區(qū)
復制緩沖區(qū)這個名詞看著很陌生,但是我們之前在聊主從同步時講過,主從全量同步期間從節(jié)點會加載主節(jié)點的RDB文件,這時主節(jié)點同樣還能寫入數(shù)據(jù),但是從節(jié)點在加載RDB文件沒辦法實時同步,所以Redis就為每一個從節(jié)點開辟了一片空間,用來存放主從全量同步期間產(chǎn)生的操作命令,這就是replication buffer,也就是復制緩沖區(qū)。
復制緩沖區(qū)溢出
復制緩沖區(qū)什么時候會溢出呢?
- 當從節(jié)點在加載RDB文件這個過程中如果存在大量的寫操作就會造成復制緩沖區(qū)內存溢出。
- 從節(jié)點加載RDB文件的時間過長。
發(fā)生溢出后,主節(jié)點會關閉與從節(jié)點的連接,導致全量同步失敗。
解決復制緩沖區(qū)溢出
控制主節(jié)點實例的大小,減小生成的RDB文件,這樣就能減少從節(jié)點加載RDB文件的時間,減小復制緩沖區(qū)的壓力。
從節(jié)點其本質就是主節(jié)點的特殊客戶端,所以使用的是輸出緩沖區(qū)(也就是指replication buffer),可以設置client-output-buffer-limit replica 256mb 64mb 60
擴大緩沖區(qū)大小。
注意:主節(jié)點上的復制緩沖區(qū)會為每一個從節(jié)點分配一個,那么從節(jié)點的數(shù)量過多即使每個從節(jié)點沒有達到maxmemory,但累加的結果也會給主節(jié)點帶來內存壓力。
復制積壓緩沖區(qū)
復制積壓緩沖區(qū)溢出
主從集群在寫操作時會將操作寫入復制緩沖區(qū)和復制積壓緩沖區(qū)中,一旦網(wǎng)絡發(fā)送故障后恢復連接,在2.8版本之前主從節(jié)點會進行全量同步開銷非常大,所以2.8版本后還是采用了增量同步,僅僅將網(wǎng)絡斷開這段時間的操作同步給從節(jié)點,所以在網(wǎng)絡恢復連接后從節(jié)點會將自己的復制偏移量slave_repl_offset發(fā)送給主節(jié)點,主節(jié)點將自身的寫入偏移量master_repl_offset和slave_repl_offset在復制積壓緩沖區(qū)中做對比得到網(wǎng)絡斷連期間的操作。
復制積壓緩沖區(qū)又叫repl_backlog_buffer,是一個環(huán)形緩沖區(qū),同步示意圖如下。
復制積壓緩沖區(qū)溢出其實也就是因為復制積壓緩沖區(qū)是一個有限環(huán)形結構,一般主節(jié)點寫入偏移量要大于從節(jié)點的讀取偏移量,但如果寫入偏移量覆蓋了從節(jié)點的讀取偏移量這就引發(fā)了復制積壓緩沖區(qū)溢出。
解決復制積壓緩沖區(qū)溢出
一般是調整repl_backlog_size這個參數(shù)的大小,擴大復制積壓緩沖區(qū)的大小,減小主節(jié)點寫入偏移量覆蓋從節(jié)點讀取偏移量的風險。
原文鏈接:https://blog.csdn.net/zzf1233/article/details/124719816
相關推薦
- 2022-05-31 如何使用yolov5輸出檢測到的目標坐標信息_python
- 2022-06-07 ASP.NET?Core依賴關系注入_基礎應用
- 2022-07-28 Python實現(xiàn)Word文檔樣式批量處理_python
- 2022-06-20 基于C#實現(xiàn)語音識別功能詳解_C#教程
- 2022-04-11 解決git 錯誤error: failed to push some refs to......
- 2023-05-18 深入了解Android?Okio的超時機制_Android
- 2022-02-13 Chrome控制臺報錯:無法加載 SourceMap 錯誤:狀態(tài)代碼 404,net::ERR_HT
- 2024-03-03 layuiadmin新建tabs標簽頁,點擊保存,打開新的標簽頁并刷新
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結構-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支