<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Redis key 消失之謎

      作者:vivo 互聯網存儲團隊 - Lin Haiwen、Xu Xingbao

      本文從一次生產環境業務服務報錯,逐步對問題進行定位,深入分析之后發現導致問題的原因,給出相應的優化方法,提升業務可用性。

       

      1分鐘看圖掌握核心觀點??

      圖片

      一、問題描述

      1.1 報錯信息

      應用服務報錯,通過監控日志發現凌晨2點的時候,應用報錯獲取不到Redis key。

       

      1.2 告警與監控信息

      首先想到是否由于內存滿導致的key淘汰,生產的所有Redis都有設置內存告警,但沒有收到內存告警信息;(內存告警需要每隔10秒,連續3次觸發才會告警。)

      從監控圖中,可以看到Redis內存稍有增長,但使用率一直偏低,并沒有達到使用率告警。

      圖片

      查看監控信息:在問題時間點,發生了大量的key過期,初步懷疑是由于key批量設置了過期時間,正好到期了導致大量key失效。

      圖片

      查看Redis錯誤日志,沒有發現異常。

       

      二、問題定位

      • 基于前面的監控,初步懷疑是key設置了過期時間導致失效。

      • 是否有上線其他新功能導致?

       

      但是業務反饋不是由于設置過期時間導致;并且第二天問題復現,因此繼續深入定位。

      2.1 key是否過期

      • 查看淘汰策略

      • 查看key過期時間

       

      初步判斷確實不是因為key過期導致的大量淘汰,這里TTL接近5天,但是連著2天出現問題,因此不應該是過期時間到了導致。

      xxx:xxx> config get'maxmemory-policy'
      1)"maxmemory-policy"
      2)"volatile-lru"
      xxx:xxx> ttl finance:xxxx_cms_version_10000
      -> Redirected to slot [9229] located at xxx:xxx
      (integer)387585
      xxx:xxx> ttl finance:xxxcms_basic_data_10423
      (integer)387574

      key是被刪除還是淘汰?查看監控,發現存在key確實被淘汰,說明接下來需要考慮內存問題。

      圖片

       

      2.2 是否內存滿了

      發現確實短時間內存寫滿了,一開始查看監控由于時間拉的比較長,查看增長趨勢沒發現內存寫滿情況,但是由于沒有達到告警條件,沒有滿足連著3次觸發閾值,故沒有觸發告警。

      同時內存用滿問題持續時間較短,約10分鐘左右。

      圖片

       

      其他指標檢查,發現出現問題時client_longest_output_list指標存在明顯突刺,該指標非常可疑。

      圖片

       

      請求量的大漲,懷疑是請求堆積導致buffer增長使得內存寫滿。但是此時還有疑點:寫入也上漲,是否是由于讀請求積壓導致,還是因為寫入數據導致內存滿?

      2.3 找出內存漲的來源

      設置定時任務,對出問題時間點前后20分鐘這段時間進行抓包分析。

      對比出問題前后幾分鐘的請求,對應時間點請求量飆升,并且請求量來源基本是get請求,set請求也少量增長。

      4860 get finance:xxxx__10122
      4925 get finance:xxxx__10032
      4945set finance:xxxx_data_10013-0
      4947 get finance:xxxx_data_10013_cms_version_10000
      4976 get finance:xxxx__10251
      5054set finance:xxxx__undefined
      5098 get finance:xxxx__10018
      8729 get finance:xxxx_data_10415_cms_version_10000
      9152 get finance:xxxx_data_10401_cms_version_10000
      9553 get finance:xxxx_data_10228_cms_version_10000
      9597 get finance:xxxx_data_10213_cms_version_10000
      9622 get finance:xxxx_data_10032_cms_version_10000
      9647 get finance:xxxx_data_10347_cms_version_10000
      9674 get finance:xxxx_data_10182_cms_version_10000
      9742 get finance:xxxx_data_10251_cms_version_10000
      10085 get finance:xxxx_data_10019_cms_version_10000
      23064 get finance:xxxx__10423
      45176 get finance:xxxx_data_10423_cms_version_10000 
      
      [root@db-prd-xxx.v-bj-3.vivo.lan:/data/redis/scpdir]
      
      # cat 0807.cap | grep '2024-08-07 01:59'|awk '{print $8,$10}'|sort |uniq -c |sort -k 1 -n

       

      同時也對set的內容進行分析,發現set的數據并不足使內存寫滿;且上面監控可以看到,內存寫滿問題持續時間很短,因此應該不是數據增長導致。

      進一步對get請求來源分析:

       

      結合 IP來源以及 keyname;跟業務同學溝通確認:

      由于業務讀請求量大漲導致,業務請求從每分鐘27w左右上漲到70w左右,主要有:

      2.4 機制分析

      內存用量上漲超限會觸發Redis節點基于已經配置的volatile-lru策略進行過期數據淘汰,所以需要找到內存上漲的來源。基于監控指標排查分析,基本確定了發生異常期間沒有集中的大量數據寫入,反而發現大量網絡數據的輸出,抓包也印證了此時節點主要是在處理get命令讀請求。進一步地發現了client-output-buffer-limit這個指標出現異常上漲,才最終鎖定到Redis的回包積壓問題。

       

      關于Redis的結果回包邏輯,首先要了解Redis的結果存儲空間設計。Redis針對每一個連接客戶端都會初始化一個大小為16K的靜態的buf區域和一個空的鏈表結果,相關聲明代碼如下:

      #define REDIS_REPLY_CHUNK_BYTES (16*1024) /* 16k output buffer */
      char buf[REDIS_REPLY_CHUNK_BYTES];
      list *reply;
      c->reply = listCreate();

       

      對于Redis而言正常執行的命令都會有數據回包,而回包結果都需要在客戶端中做暫存。Redis是如何結合以上兩個數據進行結果存儲的呢?主要邏輯是如果靜態buf區域能夠滿足回包結果存儲,即結果不大于16k,那么結果就會存儲靜態buf中,將結果不斷插入reply鏈表中;同時我們都知道Redis支持豐富的數據類型和操作命令,有些批量數據讀取命令的結果可能會有很多字段,這些字段也會作為一個個鏈表元素追加到reply鏈表中。正常情況下,我們在Redis節點上執行info clients命令可以獲得如下客戶端的統計信息:

       > info clients 
       # Clients 
       connected_clients:  1
       client_longest_output_list:  0
       client_biggest_input_buf:  0
       blocked_clients:  

      其中的client_longest_output_list字段代表此時節點的所有連接客戶端中回包結果的緩存情況。

       

      但是按照之前服務監控和抓包結果分析,具體執行的指令都是get,實際數據也沒有超過16k大小,并沒有滿足將結果存儲到鏈表的條件。這里有個經常被忽略的場景,就是Redis其實支持pipeline命令執行方式的,簡單來說就是Redis支持一次性接收一個客戶端的多個指令,具體執行過程中會把這些指令的結果不斷暫存,然后在后續流程中集中回包,如果這時候不能及時地把數據通過網絡發出去,就有可能出現reply鏈表長度激增的現象,進而導致客戶端占用內存激增,這正是我們本次遇到的場景。

      圖片

       

      Redis的maxmemory參數限制的是Redis實例可以使用的最大內存,這部分內存主要包括以下幾個部分:業務數據占用的內存、客戶端連接的輸入/輸出緩沖區、復制積壓緩沖區、AOF 緩沖區以及其他一些內部開銷。

       

      具體來說,Redis 的maxmemory 限制包括:

      1. 業務數據占用的內存,這部分是用戶在Redis中存儲的數據。

      2. 客戶端連接的輸入/輸出緩沖區,用于暫存客戶端發送的命令和Redis 返回給客戶端的數據。

      3. 復制積壓緩沖區:用于主從復制,當從節點斷線重連時,可以從這個緩沖區拉取丟失的數據。

      4. AOF 緩沖區:用于持久化,當開啟AOF 持久化時,Redis 會將寫操作追加到AOF 緩沖區,然后異步地寫入AOF 文件。

      5. 其他內部開銷:包括Redis 進程本身的一些數據結構、對象、碎片內存等。

       

      因此,在設置Redis 的maxmemory 參數時,需要綜合考慮業務數據的內存占用、各個緩沖區的大小以及內存碎片率等因素,合理地分配內存,避免出現內存溢出或性能下降的問題。

       

      三、問題解決

      3.1 緊急修復

      • 臨時擴大Redis集群內存,避免內存寫滿。

      • 限制client-output-buffer-limit大小,避免由于請求過大導致內存突增。

      • 業務限流&削峰,避免請求量突增。

      • 增加兜底機制,如果由于Redis key被淘汰,則去MySQL查詢,避免業務直接報錯。

       

      3.2 根本解決

      業務進行業務邏輯優化,將請求打散,避免同一時間集中大量請求Redis。

       

      四、總結

      本次問題是由于業務集中請求Redis,導致緩存積壓內存增長達到最大內存限制,觸發Redis淘汰策略對key進行驅逐。key被淘汰丟失后,需要增加兜底機制去DB側請求避免業務報錯。雖然Redis性能比較好,但是也要盡量打散請求,合理評估存儲側的性能。

       

      同時,對于Redis淘汰策略,對于數據比較重要的集群,可以考慮使用不驅逐的方式。合理設置TTL保留時間,把Redis的內存使用率保持在安全的區域。

       

      posted @ 2025-10-30 10:49  vivo互聯網技術  閱讀(188)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 中文国产成人久久精品小说| 日韩高清亚洲日韩精品一区二区| 自慰无码一区二区三区| 成人又黄又爽又色的视频| 中文字幕av无码免费一区| 亚洲国产午夜精品福利| 亚洲av午夜成人片| 边添小泬边狠狠躁视频| 亚洲国产成人久久综合区| 亚洲人成色99999在线观看| 色欲久久久天天天综合网| h无码精品动漫在线观看| 亚洲成av一区二区三区| 日韩有码中文在线观看| 综合亚洲网| 国产一区二区精品久久呦| 日本www一道久久久免费| 亚洲精品三区四区成人少| 啦啦啦视频在线日韩精品| 金昌市| 四虎成人高清永久免费看| 国产一区二区日韩在线| 日韩人妻无码精品久久| 18禁亚洲深夜福利人口| 亚洲国产高清精品线久久| 日韩有码中文字幕国产| 亚洲av本道一区二区| 亚洲人成18在线看久| 色偷偷女人的天堂亚洲网| 欧美熟妇乱子伦XX视频| 扶沟县| 天天爽夜夜爽人人爽曰| 国产视色精品亚洲一区二区| 亚洲无人区一码二码三码| 亚洲AV国产福利精品在现观看| 97久久综合亚洲色hezyo| 免费看亚洲一区二区三区| 精品国产AⅤ无码一区二区 | 精品久久综合日本久久网| 亚洲一区二区约美女探花| 久久综合伊人|