雲原生記憶體資料庫Tair可提供高效的資料庫服務,當記憶體不足時,可能導致Key頻繁被逐出、回應時間上升、QPS(每秒訪問次數)不穩定等問題,進而影響業務運行。通常情況下,當記憶體使用量率超過95%時需要及時關注。
Tair記憶體佔用介紹
Redis的記憶體佔用主要由以下三部分組成:
記憶體佔用 | 說明 |
鏈路記憶體(動態) | 主要包括Input Buff、Output Buff、JIT Overhead、Fake Lua Link、Lua執行緩衝等,例如可執行INFO命令,通過返回結果的Clients中查看用戶端緩衝資訊。 說明 Input buff與Output buff與每個用戶端的串連有關,通常較小。當執行用戶端Range類操作或大Key收發較慢時,Input buff與Output buff佔用的記憶體會增大,從而影響資料區,甚至會造成記憶體溢出OOM(Out Of Memory)。 |
資料記憶體 | 使用者資料區,即實際儲存的Value資訊,通常作為重點分析的對象。 |
管理記憶體(靜態) | 啟動時較小且相對恒定,該地區由管理資料的Hash記憶體開銷、Repl-buff與aof-buff的記憶體開銷(約32 MB~64 MB)等構成。 說明 當Key數量特別多時(例如幾億個),會佔用較大的記憶體。 |
說明 大部分OOM情境是由於動態記憶體管理失效引起,例如限流時請求堆積導致動態記憶體快速上升、過於複雜或不合理的Lua指令碼也可能導致OOM。
步驟一:分析記憶體使用量情況
- 查詢指定時段的記憶體使用量率資訊,具體操作,請參見查看效能監控。
- 查詢歷史累計逐出的Key總數和命令的最大時延,分析是否呈現明顯的上升趨勢。
以下樣本中,在同一時間點(2021年1月7日16點整),歷史累計逐出的Key總數和命令的最大時延均呈現顯著上升趨勢,表明存在記憶體不足的問題。
說明 需關注的監控指標為Evicted Keys(歷史累計逐出的Key總數)和Max Rt(資料節點從接收命令到發出響應最大時延)。 - 可選:當Tair的記憶體使用量率不符合預期時,可執行下述步驟詳細分析記憶體使用量情況。
- 通過redis-cli串連Tair。
- 在Tair命令列中,執行MEMORY STATS命令查詢記憶體使用量詳情。Tair執行個體的記憶體開銷主要由兩部分組成:
- 業務資料的記憶體開銷,該部分一般作為重點分析對象。
- 非業務資料的記憶體開銷,例如主備複製的積壓緩衝區、Tair進程初始化消耗的記憶體等。
返回樣本及各參數對應的解釋如下:
說明 下述返回資訊中,記憶體數值的單位為位元組。1) "peak.allocated" //Tair進程自啟動以來消耗記憶體的峰值。 2) (integer) 79492312 3) "total.allocated" //Tair使用其分配器分配的總位元組數,即當前的總記憶體使用量量。 4) (integer) 79307776 5) "startup.allocated" //Tair啟動時消耗的初始記憶體量。 6) (integer) 45582592 7) "replication.backlog" //複製積壓緩衝區的大小。 8) (integer) 33554432 9) "clients.slaves" //主從複製中所有從節點的讀寫緩衝區大小。 10) (integer) 17266 11) "clients.normal" //除從節點外,所有其他用戶端的讀寫緩衝區大小。 12) (integer) 119102 13) "aof.buffer" //AOF持久化使用的緩衝和AOF重寫時產生的緩衝。 14) (integer) 0 15) "db.0" //業務資料庫的數量。 16) 1) "overhead.hashtable.main" //當前資料庫的hash鏈表開銷記憶體總和,即中繼資料記憶體。 2) (integer) 144 3) "overhead.hashtable.expires" //用於儲存key的到期時間所消耗的記憶體。 4) (integer) 0 17) "overhead.total" //數值=startup.allocated+replication.backlog+clients.slaves+clients.normal+aof.buffer+db.X。 18) (integer) 79273616 19) "keys.count" //當前Tair執行個體的key總數 20) (integer) 2 21) "keys.bytes-per-key" //當前Tair執行個體每個key的平均大小,計算公式:(total.allocated-startup.allocated)/keys.count。 22) (integer) 16862592 23) "dataset.bytes" //純業務資料佔用的記憶體大小。 24) (integer) 34160 25) "dataset.percentage" //純業務資料佔用的記憶體比例,計算公式:dataset.bytes*100/(total.allocated-startup.allocated)。 26) "0.1012892946600914" 27) "peak.percentage" //當前總記憶體與歷史峰值的比例,計算公式:total.allocated*100/peak.allocated。 28) "99.767860412597656" 29) "fragmentation" //記憶體的片段率。 30) "0.45836541056632996"
- 在Tair命令列中,執行MEMORY USAGE命令查詢指定Key消耗的記憶體(單位為位元組)。
命令執行樣本:
MEMORY USAGE Key0089393003
返回資訊如下:
(integer) 1000072
- 在Tair命令列中,執行MEMORY DOCTOR命令擷取記憶體診斷建議。MEMORY DOCTOR會從以下維度為Tair執行個體的提供記憶體診斷建議,您可以根據診斷建議制定相應的最佳化策略:
int empty = 0; /* Instance is empty or almost empty. */ int big_peak = 0; /* Memory peak is much larger than used mem. */ int high_frag = 0; /* High fragmentation. */ int high_alloc_frag = 0;/* High allocator fragmentation. */ int high_proc_rss = 0; /* High process rss overhead. */ int high_alloc_rss = 0; /* High rss overhead. */ int big_slave_buf = 0; /* Slave buffers are too big. */ int big_client_buf = 0; /* Client buffers are too big. */ int many_scripts = 0; /* Script cache has too many scripts. */
步驟二:最佳化記憶體使用量率
- 查詢現有的Key是否符合業務預期,及時清理無用的Key。
- 通過緩衝分析功能,分析大Key分布和Key的TTL到期策略。具體操作,請參見離線全量Key分析。
- 分析Key是否有合理的TTL策略。說明 以下樣本中,所有的Key均未設定到期時間,建議根據業務需求來衡量,並在應用端設定合理的到期時間。
- 對大Key進行評估,然後從業務方向對大Key進行拆分。
- 分析Key是否有合理的TTL策略。
- 根據業務需求,設定合理的資料逐出策略(即調整maxmemory-policy參數的值)。具體操作,請參見設定執行個體參數。
- 根據業務需求,設定合理的到期Key主動刪除的執行頻率(即調整hz參數的值)。具體操作,請參見調整Tair定期任務的執行頻率。說明 hz的取值建議在100以內,如果該值過大將對CPU的使用率產生較大影響。您也可以設定為自動調整(要求執行個體為記憶體型或持久記憶體型),具體操作,請參見自動調整Tair定期任務的執行頻率。
- 經過上述步驟最佳化後,流量使用率依舊較高,可評估升級至更大記憶體的規格,以承載更大的網路流量。具體操作,請參見變更執行個體配置。說明 在正式升級執行個體的規格前,您可以先購買一個隨用隨付的執行個體,測試要升級到的目標規格是否能夠滿足業務的負載需求,測試完成後可將其釋放。關於如何釋放執行個體,請參見釋放隨用隨付執行個體。