高效利用redis記憶體需要理解記憶體消耗在**,然後在管理記憶體,優化記憶體。
記憶體消耗分析、管理記憶體的原理和方法、記憶體優化技巧
8.1 記憶體消耗
想理解redis記憶體,首先要知道redis記憶體消耗在哪些方面。可以通過引數調整和合理使用來規避記憶體浪費。記憶體消耗可以分為程序自身消耗和子程序消耗
8.1.1 記憶體使用統計
1 通過執行info memory獲取記憶體相關指標
需要重點關注的指標有:used_memory_rss和used_memory以及它們的比值mem_fragmentation_radio
當mem_fragmentation_radio>1時,說明used_memory_rss-used_memory多出的部分記憶體沒有用於資料儲存,而是被記憶體碎片所消耗,如果兩者相差很大,說明碎片率嚴重
當mem_fragmentation_radio<1時,作業系統把redis記憶體交換(swap)到硬碟導致。
8.1.2 記憶體消耗劃分
1 物件記憶體
占用記憶體最大的一塊,儲存使用者所有資料。記憶體消耗=sizeof(keys)+sizeof(values)
注意:避免使用過長的鍵和合理預估並監控value物件占用情況,避免記憶體溢位
2 緩衝記憶體
客戶端緩衝、複製積壓緩衝區、aof緩衝區
客戶端緩衝:所有接入到redis伺服器tcp連線的輸入輸出緩衝。
普通客戶端:除了複製和訂閱的客戶端之外的所有連線?不明白
從客戶端:主結點為每個結點單獨建立一條連線用於命令複製
訂閱客戶端:當使用發布訂閱功能時,連線客戶端使用單獨的輸出緩衝區
輸入輸出緩衝區在大流量的場景中容易失控,造成redis記憶體的不穩定,需要重點監控
複製積壓緩衝區
可重用的固定大小緩衝區用於實現部分複製功能
aof緩衝區
這部分空間用於在redis重寫期間儲存最近寫入命令
3 記憶體碎片
記憶體分配器採用jemalloc,有可選的。記憶體分配器為了更好的管理和重複利用記憶體,分配記憶體策略一般採用固定範圍的記憶體塊進行分配
出現高記憶體碎片問題解決方式:
資料對齊和安全重啟
8.1.3 子程序記憶體消耗
redis產生的子程序並不需要消耗1倍的父程序記憶體,實際消耗根據期間寫入命令量決定,但是依然要預出一些記憶體防止溢位
需要設定sysctl vm.overcommit_memory=1允許核心可以分配所有的物理記憶體,防止redis程序執行fork時因系統剩餘記憶體不足而失敗
排查當前系統是否支援並開啟thp,如果開啟建議關閉,防止copy-on-write期間記憶體過度消耗
8.2 記憶體管理
通過控制記憶體上限和**策略實現記憶體管理
8.2.1 設定記憶體上限
限制記憶體使用的目的:
用於快取場景,當超出記憶體上限maxmemory時使用lru等刪除策略釋放空間
防止所用記憶體超過伺服器物理記憶體
config set maxmemory進行動態修改,即修改最大可用記憶體。
redis預設無限使用伺服器記憶體,為防止極端情況,建議所有的redis程序都要設定maxmemory,在保證物理記憶體可用的情況下,系統中所有redis例項可以調整maxmemory引數來達到自由伸縮記憶體的目的
8.2.3 記憶體**策略
1 刪除過期鍵物件
惰性刪除和定時任務刪除
2 記憶體溢位控制策略
建議線上記憶體工作在maxmemory>used_memory狀態下,避免頻繁記憶體**開銷
8.3 記憶體優化
8.3.1 redisobject物件
高併發寫入場景中,在條件允許的情況下,建議字串長度控制在39位元組以內,減少建立redisobject記憶體分配次數,從而提高效能
8.3.2 縮減鍵值物件
減少key長度和減少value長度
8.3.3 共享物件池
8.3.4 字串優化
所有的鍵都是字串型別。
1 字串結構
內部簡單實現動態字串
2 預分配機制
3 字串重構
不一定把每份資料作為字串整體儲存,
8.3.5 編碼優化
1 了解編碼
所謂編碼,就是具體使用哪種底層資料結構來實現 object encoding 獲取編碼型別
多種編碼型別:是想通過不同編碼實現效率和空間的平衡
2 控制編碼型別
輸入寫入的時候自動完成,不可逆
3 ziplist編碼
4 inset編碼
集合set型別編碼的一種,內部表現為儲存有序、不重複的整數集。
1 encoding:整數表示型別,根據集合內最長整數值確定型別,整數型別劃分為三種:int-16、int-32、int-64
2 length 表示集合元素個數
3 contents 整數陣列,按從小到大順序儲存
intset儲存的整數型別根據長度劃分,儲存的整數型別超出當前型別時,將自動觸發公升級不回退,公升級操作將會導致重新申請記憶體空間,把原有資料拷貝到新陣列。
8.3.6 控制鍵的數量
對於儲存相同資料內容利用redis的資料結構降低外層鍵的數量,可以節省大量記憶體。
hash結構降低鍵數量分析
根據鍵規模在客戶端通過分組對映到一組hash物件中
hash的field可用於記錄原始key字串,方便雜湊查詢
hash的value儲存原始值物件,確保不要超過hash-max-ziplist-value限制
8.4 本章重點回顧
redis學習筆記 第8章 理解記憶體
8.1 記憶體消耗 物件記憶體 物件記憶體是redis記憶體占用最大的一塊,儲存著使用者所有的資料。redis所有的資料都採用key value資料型別,每次建立鍵值對時,至少建立兩個型別物件 key物件和value物件。物件記憶體消耗可以簡單理解為sizeof keys sizeof values...
第 8 章 記憶體管理策略
為了實現效能改進,應將多個程序儲存在記憶體中,也就是說必須共享記憶體。記憶體是現代計算機執行的核心。記憶體由乙個很大的位元組陣列來組成,每個位元組都有各自的位址。8.1.1 基礎硬體 cpu可以直接訪問的通用儲存只有記憶體和處理器內建的暫存器。每個程序都有乙個獨立的記憶體空間,可以保護程序不會互相影...
第8章指標
1.指標 指標是儲存記憶體位址的變數。在記憶體中每一塊儲存單元都有相對應的唯一的位址編號,指標就是一塊儲存這種編號的空間 2.對於乙個變數可以用 符號來獲取它的位址 int a int p a 什麼樣的變數,就需要宣告對應的型別的指標。這是為了告訴系統,我從這個位址開始要讀取多少位的記憶體塊,才能正...