詳細解析Redis記憶體滿了怎麼去優化
這篇文章為大家帶來了關於Redis的相關知識,其中主要介紹了redis的記憶體滿了應該怎麼優化的相關問題,還包括了淘汰機制、LRU演算法以及處理淘汰的數據,希望對大家有幫助。
推薦學習:Redis學習教學
Redis記憶體滿了怎麼辦?怎麼優化記憶體?
MySQL裡有2000w數據,redis中只存20w的數據,如何保證redis中的數據都是熱點數據
redis內存數據集大小上升到一定大小的時候,就會施行資料淘汰策略。
Redis主要消耗什麼實體資源?
記憶體。
Redis的記憶體用完了會發生什麼事?
如果達到設定的上限,Redis的寫指令會回傳錯誤訊息(但是讀取指令還可以正常回傳。)或者你可以設定記憶體淘汰機制,當Redis達到記憶體上限時會沖刷掉舊的內容。
談談快取資料的淘汰機制
Redis 快取有哪些淘汰策略?
- 不進行資料淘汰的策略,只有 noeviction 這一種。
會進行淘汰的7 種策略,我們可以再進一步根據淘汰候選資料集的範圍把它們分成兩類:
- 在設定了過期時間的數據中進行淘汰,包括volatile-random、volatile-ttl、volatile-lru、volatile-lfu四種。
- 在所有資料範圍內進行淘汰,包括 allkeys-lru、allkeys-random、allkeys-lfu三種。
策略 | 規則 |
---|---|
volatile-ttl | 在篩選時,會針對設定了過期時間的鍵值對,根據過期時間的先後進行刪除,越早過期的越先被刪除。 |
volatile-random | 在設定了過期時間的鍵值對中,進行隨機刪除。 |
volatile-lru | 使用LRU 演算法篩選設定了過期時間的鍵值對 |
使用LFU 演算法選擇設定了過期時間的鍵值對 |
談談LRU演算法
是按照最近最少使用的原則來篩選數據,最不常用的數據會被篩選出來,而最近頻繁使用的數據會留在快取中。
那具體是怎麼篩選的呢? LRU 會把所有的資料組織成一個鍊錶,鍊錶的頭和尾分別表示 MRU 端和 LRU 端,分別代表最近最常使用的資料和最近最不常用的資料。
LRU 演算法背後的想法非常樸素:它認為剛剛被訪問的數據,肯定還會再次訪問,所以就把它放在MRU 端;長久不訪問的數據,肯定就不會再被存取了,所以就讓它逐漸後移到LRU 端,在快取滿時,就優先刪除它。
問題:LRU 演算法在實際實作時,需要用鍊錶管理所有的快取數據,這會帶來額外的空間開銷。而且,當有資料被存取時,需要在鍊錶上把該資料移動到 MRU 端,如果有大量資料被訪問,就會帶來很多鍊錶移動操作,會很耗時,進而降低 Redis 快取效能。
解決:
在 Redis 中,LRU 演算法被做了簡化,以減輕資料淘汰對快取效能的影響。具體來說,Redis 預設會記錄每個資料的最近一次存取的時間戳記(由鍵值對資料結構 RedisObject 中的 lru 欄位記錄)。然後,Redis 在決定淘汰的數據時,第一次會隨機選出 N 個數據,把它們當作一個候選集合。接下來,Redis 會比較這 N 個資料的 lru 字段,把 lru 字段值最小的資料從快取中淘汰出去。
當需要再次淘汰資料時,Redis 需要挑選資料進入第一次淘汰時所建立的候選集合。這兒的挑選標準是:能進入候選集合的資料的 lru 欄位值必須小於候選集合中最小的 lru 值。當有新資料進入候選資料集後,如果候選資料集中的資料個數達到了 maxmemory-samples,Redis 就把候選資料集中 lru 欄位值最小的資料淘汰出去。
使用建議:
- 優先使用 allkeys-lru 策略。這樣,可以充分利用 LRU 這項經典快取演算法的優勢,把最近最常存取的資料留在快取中,提升應用程式的存取效能。如果你的業務資料中有明顯的冷熱資料區分,我建議你使用 allkeys-lru 策略。
- 如果業務應用中的資料存取頻率相差不大,沒有明顯的冷熱資料區分,建議使用 allkeys-random 策略,隨機選擇淘汰的資料就行。
- 如果你的業務中有置頂的需求,例如置頂新聞、置頂視頻,那麼,可以使用 volatile-lru 策略,同時不給這些置頂數據設定過期時間。這樣一來,這些需要置頂的資料一直不會被刪除,而其他資料會在過期時根據 LRU 規則進行篩選。
如何處理被淘汰的資料?
一旦被淘汰的數據選定後,如果這個數據是乾淨數據,那麼我們就直接刪除;如果這個數據是髒數據,我們需要把它寫回數據庫。
那要怎麼判斷一個資料到底是乾淨的還是髒的呢?
- 乾淨資料和髒資料的差別在於,和最初從後端資料庫讀取時的值相比,有沒有被修改過。乾淨資料一直沒有被修改,所以後端資料庫裡的資料也是最新值。在替換時,它可以直接刪除。
- 而髒資料就是曾經被修改過的,已經和後端資料庫中保存的資料不一致了。此時,如果不把髒資料寫回資料庫中,這個資料的最新值就遺失了,就會影響應用程式的正常使用。
即使淘汰的資料是髒數據,Redis 也不會把它們寫回資料庫。所以,我們在使用 Redis 快取時,如果資料被修改了,需要在資料修改時就將它寫回資料庫。否則,這個髒資料被淘汰時,會被 Redis 刪除,而資料庫裡也沒有最新的資料了。
Redis怎麼優化記憶體?
1、控制key的數量:當使用Redis儲存大量資料時,通常會存在大量鍵,過多的鍵同樣會消耗大量記憶體。 Redis本質是一個資料結構伺服器,它為我們提供多種資料結構,如hash,list,set,zset 等結構。使用Redis時不要進入一個誤區,大量使用get/set這樣的API,把Redis當成Memcached使用。對於儲存相同的資料內容利用Redis的資料結構降低外層鍵的數量,也可以節省大量記憶體。
2、縮減鍵值對象,降低Redis記憶體使用最直接的方式就是縮減鍵(key)和值(value)的長度。
- key長度:如在設計鍵時,在完整描述業務情況下,鍵值越短越好。
- value長度:值物件縮減比較複雜,常見需求是把業務物件序列化成二進位陣列放入Redis。首先應該在業務上精簡業務對象,去掉不必要的屬性避免儲存無效資料。其次在序列化工具選擇上,應該選擇更有效率的序列化工具來降低位元組數組大小。
3、編碼最佳化。 Redis對外提供了string,list,hash,set,zet等類型,但是Redis內部針對不同類型存在編碼的概念,所謂編碼就是具體使用哪種底層資料結構來實現。編碼不同將直接影響資料的記憶體佔用和讀寫效率。
- 1、redisObject物件
#type欄位:
利用集合類型數據,因為通常情況下很多小的Key-Value可以用更緊湊的方式存放在一起。盡可能使用散列表(hashes),散列表(是說散列表裡面儲存的數少)使用的記憶體非常小,所以你應該盡可能的將你的資料模型抽象化到一個散列表裡面。例如你的web系統中有一個用戶對象,不要為這個用戶的名稱,姓氏,郵箱,密碼設定單獨的key,而是應該把這個用戶的所有資訊儲存到一張散列表裡面。
encoding欄位:
採用不同的編碼實作記憶體佔用有明顯差異
lru欄位:
開發提示:可以使用scan object idletime 命令批量查詢哪些鍵長時間未被訪問,找出長時間不訪問的鍵進行清理降低內存佔用。
refcount欄位:
當物件為整數且範圍在[0-9999]時,Redis可以使用共享物件的方式來節省記憶體。
ptr欄位 :
開發提示:高並發寫入場景中,在條件允許的情況下建議字串長度控制在39位元組以內,減少創建redisObject記憶體分配次數從而提高效能。
- 2、縮減鍵值物件
降低Redis記憶體使用最直接的方式就是縮減鍵(key)和值(value)的長度。
可以使用通用壓縮演算法壓縮json,xml後再存入Redis,從而降低記憶體佔用
- 3、共享物件池
物件共享池指Redis內部維護[0-9999]的整數物件池。創建大量的整數類型redisObject存在記憶體開銷,每個redisObject內部結構至少佔16字節,甚至超過了整數自身空間消耗。所以Redis記憶體維護一個[0-9999]的整數物件池,用於節約記憶體。除了整數值對象,其他型別如list,hash,set,zset內部元素也可以使用整數物件池。 因此開發中在滿足需求的前提下,盡量使用整數物件以節省記憶體。
當設定maxmemory並啟用LRU相關淘汰策略如:volatile-lru,allkeys-lru時,Redis禁止使用共享物件池。
為什麼開啟maxmemory和LRU淘汰策略後物件池無效?
LRU演算法需要取得物件最後被存取時間,以便淘汰最長未存取數據,每個物件最後存取時間儲存在redisObject物件的lru欄位。物件共享意味著多個引用共享同一個redisObject,這時lru欄位也會被共享,導致無法取得每個物件的最後存取時間。如果沒有設定maxmemory,直到記憶體被用盡Redis也不會觸發記憶體回收,所以共享物件池可以正常運作。
綜上所述,共享物件池與maxmemory LRU策略衝突,使用時需要注意。
為什麼只有整數物件池?
首先整數物件池復用的幾率最大,其次物件共享的一個關鍵操作就是判斷相等性,Redis之所以只有整數物件池,是因為整數比較演算法時間複雜度為O(1),只保留一萬個整數為了防止物件池浪費。如果是字串判斷相等性,時間複雜度變成O(n),特別是長字串更消耗效能(浮點數在Redis內部使用字串儲存)。對於較複雜的資料結構如hash,list等,相等性判斷需要O(n2)。對於單執行緒的Redis來說,這樣的開銷顯然不合理,因此Redis只保留整數共享物件池。
- 4、字串最佳化
Redis沒有採用原生C語言的字串型別而是自己實作了字串結構,內部簡單動態字串,簡稱SDS。
字串結構:
- 特點:
O(1)時間複雜度取得:字串長度,已用長度,未用長度。
可用於保存位元組數組,支援安全的二進位資料儲存。
內部實作空間預先分配機制,降低記憶體再分配次數。
惰性刪除機制,字串縮減後的空間不釋放,作為預先分配空間保留。
預先分配機制:
- 開發提示:盡量減少字串頻繁修改操作如append,setrange, 改為直接使用set修改字串,降低預分配帶來的記憶體浪費和記憶體碎片化。
字串重構:基於hash類型的次要編碼方式。
- 二級編碼怎麼用?
二級編碼方法中所採用的 ID 長度是有講究的。
涉及一個問題–Hash 類型底層結構小於設定值時使用壓縮列表,大於設定值時使用哈希表。
一旦從壓縮列表轉為了哈希表,Hash 類型會一直用哈希表進行保存,而不會再轉回壓縮列表。
在節省記憶體空間方面,哈希表就沒有壓縮列表那麼有效率。為能充分使用壓縮清單的精簡記憶體佈局,一般要控制保存在 Hash 中的元素個數。
- 5.編碼優化
使用壓縮列表ziplist編碼的hash類型依然比使用hashtable編碼的集合節省大量記憶體。
- 6.控制key的數量
開發提示:使用ziplist hash優化keys後,如果想使用逾時刪除功能,開發人員可以儲存每個物件寫入的時間,再透過定時任務使用hscan指令掃描數據,找出hash內逾時的資料項刪除即可。
當Redis記憶體不足時,首先考慮的問題不是加機器做水平擴展,應該先嘗試做記憶體優化。當遇到瓶頸時,再去考慮水平擴展。即使對於叢集化方案,垂直層面最佳化也同樣重要,避免不必要的資源浪費和叢集化後的管理成本。
推薦學習:Redis教學
#以上是詳細解析Redis記憶體滿了怎麼去優化的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

Redis集群模式通過分片將Redis實例部署到多個服務器,提高可擴展性和可用性。搭建步驟如下:創建奇數個Redis實例,端口不同;創建3個sentinel實例,監控Redis實例並進行故障轉移;配置sentinel配置文件,添加監控Redis實例信息和故障轉移設置;配置Redis實例配置文件,啟用集群模式並指定集群信息文件路徑;創建nodes.conf文件,包含各Redis實例的信息;啟動集群,執行create命令創建集群並指定副本數量;登錄集群執行CLUSTER INFO命令驗證集群狀態;使

如何清空 Redis 數據:使用 FLUSHALL 命令清除所有鍵值。使用 FLUSHDB 命令清除當前選定數據庫的鍵值。使用 SELECT 切換數據庫,再使用 FLUSHDB 清除多個數據庫。使用 DEL 命令刪除特定鍵。使用 redis-cli 工具清空數據。

要從 Redis 讀取隊列,需要獲取隊列名稱、使用 LPOP 命令讀取元素,並處理空隊列。具體步驟如下:獲取隊列名稱:以 "queue:" 前綴命名,如 "queue:my-queue"。使用 LPOP 命令:從隊列頭部彈出元素並返回其值,如 LPOP queue:my-queue。處理空隊列:如果隊列為空,LPOP 返回 nil,可先檢查隊列是否存在再讀取元素。

在CentOS系統上,您可以通過修改Redis配置文件或使用Redis命令來限制Lua腳本的執行時間,從而防止惡意腳本佔用過多資源。方法一:修改Redis配置文件定位Redis配置文件:Redis配置文件通常位於/etc/redis/redis.conf。編輯配置文件:使用文本編輯器(例如vi或nano)打開配置文件:sudovi/etc/redis/redis.conf設置Lua腳本執行時間限制:在配置文件中添加或修改以下行,設置Lua腳本的最大執行時間(單位:毫秒)

使用 Redis 命令行工具 (redis-cli) 可通過以下步驟管理和操作 Redis:連接到服務器,指定地址和端口。使用命令名稱和參數向服務器發送命令。使用 HELP 命令查看特定命令的幫助信息。使用 QUIT 命令退出命令行工具。

Redis計數器是一種使用Redis鍵值對存儲來實現計數操作的機制,包含以下步驟:創建計數器鍵、增加計數、減少計數、重置計數和獲取計數。 Redis計數器的優勢包括速度快、高並發、持久性和簡單易用。它可用於用戶訪問計數、實時指標跟踪、遊戲分數和排名以及訂單處理計數等場景。

Redis數據過期策略有兩種:定期刪除:定期掃描刪除過期鍵,可通過 expired-time-cap-remove-count、expired-time-cap-remove-delay 參數設置。惰性刪除:僅在讀取或寫入鍵時檢查刪除過期鍵,可通過 lazyfree-lazy-eviction、lazyfree-lazy-expire、lazyfree-lazy-user-del 參數設置。

在Debian系統中,readdir系統調用用於讀取目錄內容。如果其性能表現不佳,可嘗試以下優化策略:精簡目錄文件數量:盡可能將大型目錄拆分成多個小型目錄,降低每次readdir調用處理的項目數量。啟用目錄內容緩存:構建緩存機制,定期或在目錄內容變更時更新緩存,減少對readdir的頻繁調用。內存緩存(如Memcached或Redis)或本地緩存(如文件或數據庫)均可考慮。採用高效數據結構:如果自行實現目錄遍歷,選擇更高效的數據結構(例如哈希表而非線性搜索)存儲和訪問目錄信
