第8章 理解記憶體

2021-08-17 07:45:47 字數 3312 閱讀 1341

高效利用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 什麼樣的變數,就需要宣告對應的型別的指標。這是為了告訴系統,我從這個位址開始要讀取多少位的記憶體塊,才能正...