最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深入理解Redis 內(nèi)存管理

 更新時間:2025年02月06日 10:38:36   作者:濤粒子  
本文主要介紹了深入理解Redis 內(nèi)存管理,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

Redis 給緩存數(shù)據(jù)設置過期時間有什么用?

一般情況下,我們設置保存的緩存數(shù)據(jù)的時候都會設置一個過期時間。為什么呢?

內(nèi)存是有限且珍貴的,如果不對緩存數(shù)據(jù)設置過期時間,那內(nèi)存占用就會一直增長,最終可能會導致 OOM 問題。通過設置合理的過期時間,Redis 會自動刪除暫時不需要的數(shù)據(jù),為新的緩存數(shù)據(jù)騰出空間。

Redis 自帶了給緩存數(shù)據(jù)設置過期時間的功能,比如:

127.0.0.1:6379> expire key 60 # 數(shù)據(jù)在 60s 后過期
(integer) 1
127.0.0.1:6379> setex key 60 value # 數(shù)據(jù)在 60s 后過期 (setex:[set] + [ex]pire)
OK
127.0.0.1:6379> ttl key # 查看數(shù)據(jù)還有多久過期
(integer) 56

注意 ??:Redis 中除了字符串類型有自己獨有設置過期時間的命令 setex 外,其他方法都需要依靠 expire 命令來設置過期時間 。另外, persist 命令可以移除一個鍵的過期時間。

過期時間除了有助于緩解內(nèi)存的消耗,還有什么其他用么?

很多時候,我們的業(yè)務場景就是需要某個數(shù)據(jù)只在某一時間段內(nèi)存在,比如我們的短信驗證碼可能只在 1 分鐘內(nèi)有效,用戶登錄的 Token 可能只在 1 天內(nèi)有效。

如果使用傳統(tǒng)的數(shù)據(jù)庫來處理的話,一般都是自己判斷過期,這樣更麻煩并且性能要差很多。

Redis 是如何判斷數(shù)據(jù)是否過期的呢?

Redis 通過一個叫做過期字典(可以看作是 hash 表)來保存數(shù)據(jù)過期的時間。過期字典的鍵指向 Redis 數(shù)據(jù)庫中的某個 key(鍵),過期字典的值是一個 long long 類型的整數(shù),這個整數(shù)保存了 key 所指向的數(shù)據(jù)庫鍵的過期時間(毫秒精度的 UNIX 時間戳)。

過期字典是存儲在 redisDb 這個結(jié)構(gòu)里的:

typedef struct redisDb {
    ...

    dict *dict;     //數(shù)據(jù)庫鍵空間,保存著數(shù)據(jù)庫中所有鍵值對
    dict *expires   // 過期字典,保存著鍵的過期時間
    ...
} redisDb;

在查詢一個 key 的時候,Redis 首先檢查該 key 是否存在于過期字典中(時間復雜度為 O(1)),如果不在就直接返回,在的話需要判斷一下這個 key 是否過期,過期直接刪除 key 然后返回 null。

Redis 過期 key 刪除策略了解么?

如果假設你設置了一批 key 只能存活 1 分鐘,那么 1 分鐘后,Redis 是怎么對這批 key 進行刪除的呢?

常用的過期數(shù)據(jù)的刪除策略就下面這幾種:

  • 惰性刪除:只會在取出/查詢 key 的時候才對數(shù)據(jù)進行過期檢查。這種方式對 CPU 最友好,但是可能會造成太多過期 key 沒有被刪除。
  • 定期刪除:周期性地隨機從設置了過期時間的 key 中抽查一批,然后逐個檢查這些 key 是否過期,過期就刪除 key。相比于惰性刪除,定期刪除對內(nèi)存更友好,對 CPU 不太友好。
  • 延遲隊列:把設置過期時間的 key 放到一個延遲隊列里,到期之后就刪除 key。這種方式可以保證每個過期 key 都能被刪除,但維護延遲隊列太麻煩,隊列本身也要占用資源。
  • 定時刪除:每個設置了過期時間的 key 都會在設置的時間到達時立即被刪除。這種方法可以確保內(nèi)存中不會有過期的鍵,但是它對 CPU 的壓力最大,因為它需要為每個鍵都設置一個定時器。

Redis 采用的那種刪除策略呢?

Redis 采用的是 定期刪除+惰性/懶漢式刪除 結(jié)合的策略,這也是大部分緩存框架的選擇。定期刪除對內(nèi)存更加友好,惰性刪除對 CPU 更加友好。兩者各有千秋,結(jié)合起來使用既能兼顧 CPU 友好,又能兼顧內(nèi)存友好。

下面是我們詳細介紹一下 Redis 中的定期刪除具體是如何做的。

Redis 的定期刪除過程是隨機的(

#define ACTIVE_EXPIRE_CYCLE_FAST_DURATION 1000 /* Microseconds. */
#define ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC 25 /* Max % of CPU to use. */
#define ACTIVE_EXPIRE_CYCLE_ACCEPTABLE_STALE 10 /* % of stale keys after which
                                                   we do extra efforts. */

周期性地隨機從設置了過期時間的 key 中抽查一批),所以并不保證所有過期鍵都會被立即刪除。這也就解釋了為什么有的 key 過期了,并沒有被刪除。并且,Redis 底層會通過限制刪除操作執(zhí)行的時長和頻率來減少刪除操作對 CPU 時間的影響。

另外,定期刪除還會受到執(zhí)行時間和過期 key 的比例的影響:

  • 執(zhí)行時間已經(jīng)超過了閾值,那么就中斷這一次定期刪除循環(huán),以避免使用過多的 CPU 時間。
  • 如果這一批過期的 key 比例超過一個比例,就會重復執(zhí)行此刪除流程,以更積極地清理過期 key。相應地,如果過期的 key 比例低于這個比例,就會中斷這一次定期刪除循環(huán),避免做過多的工作而獲得很少的內(nèi)存回收。

Redis 7.2 版本的執(zhí)行時間閾值是 25ms,過期 key 比例設定值是 10%

#define ACTIVE_EXPIRE_CYCLE_FAST_DURATION 1000 /* Microseconds. */
#define ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC 25 /* Max % of CPU to use. */
#define ACTIVE_EXPIRE_CYCLE_ACCEPTABLE_STALE 10 /* % of stale keys after which
                                                   we do extra efforts. */

每次隨機抽查數(shù)量是多少?

expire.c中定義了每次隨機抽查的數(shù)量,Redis 7.2 版本為 20 ,也就是說每次會隨機選擇 20 個設置了過期時間的 key 判斷是否過期。

#define ACTIVE_EXPIRE_CYCLE_KEYS_PER_LOOP 20 /* Keys for each DB loop. */

如何控制定期刪除的執(zhí)行頻率?

在 Redis 中,定期刪除的頻率是由 hz 參數(shù)控制的。hz 默認為 10,代表每秒執(zhí)行 10 次,也就是每秒鐘進行 10 次嘗試來查找并刪除過期的 key。

hz 的取值范圍為 1~500。增大 hz 參數(shù)的值會提升定期刪除的頻率。如果你想要更頻繁地執(zhí)行定期刪除任務,可以適當增加 hz 的值,但這會加 CPU 的使用率。根據(jù) Redis 官方建議,hz 的值不建議超過 100,對于大部分用戶使用默認的 10 就足夠了。

下面是 hz 參數(shù)的官方注釋,我翻譯了其中的重要信息(Redis 7.2 版本)。

類似的參數(shù)還有一個 dynamic-hz,這個參數(shù)開啟之后 Redis 就會在 hz 的基礎上動態(tài)計算一個值。Redis 提供并默認啟用了使用自適應 hz 值的能力,

這兩個參數(shù)都在 Redis 配置文件 redis.conf中:

# 默認為 10
hz 10
# 默認開啟
dynamic-hz yes

多提一嘴,除了定期刪除過期 key 這個定期任務之外,還有一些其他定期任務例如關(guān)閉超時的客戶端連接、更新統(tǒng)計信息,這些定期任務的執(zhí)行頻率也是通過 hz 參數(shù)決定。

為什么定期刪除不是把所有過期 key 都刪除呢?

這樣會對性能造成太大的影響。如果我們 key 數(shù)量非常龐大的話,挨個遍歷檢查是非常耗時的,會嚴重影響性能。Redis 設計這種策略的目的是為了平衡內(nèi)存和性能。

為什么 key 過期之后不立馬把它刪掉呢?這樣不是會浪費很多內(nèi)存空間嗎?

因為不太好辦到,或者說這種刪除方式的成本太高了。假如我們使用延遲隊列作為刪除策略,這樣存在下面這些問題:

  • 隊列本身的開銷可能很大:key 多的情況下,一個延遲隊列可能無法容納。
  • 維護延遲隊列太麻煩:修改 key 的過期時間就需要調(diào)整期在延遲隊列中的位置,并且,還需要引入并發(fā)控制。

大量 key 集中過期怎么辦?

當 Redis 中存在大量 key 在同一時間點集中過期時,可能會導致以下問題:

  • 請求延遲增加: Redis 在處理過期 key 時需要消耗 CPU 資源,如果過期 key 數(shù)量龐大,會導致 Redis 實例的 CPU 占用率升高,進而影響其他請求的處理速度,造成延遲增加。
  • 內(nèi)存占用過高: 過期的 key 雖然已經(jīng)失效,但在 Redis 真正刪除它們之前,仍然會占用內(nèi)存空間。如果過期 key 沒有及時清理,可能會導致內(nèi)存占用過高,甚至引發(fā)內(nèi)存溢出。

為了避免這些問題,可以采取以下方案:

  • 盡量避免 key 集中過期: 在設置鍵的過期時間時盡量隨機一點。
  • 開啟 lazy free 機制: 修改 redis.conf 配置文件,將 lazyfree-lazy-expire 參數(shù)設置為 yes,即可開啟 lazy free 機制。開啟 lazy free 機制后,Redis 會在后臺異步刪除過期的 key,不會阻塞主線程的運行,從而降低對 Redis 性能的影響。

Redis 內(nèi)存淘汰策略了解么?

相關(guān)問題:MySQL 里有 2000w 數(shù)據(jù),Redis 中只存 20w 的數(shù)據(jù),如何保證 Redis 中的數(shù)據(jù)都是熱點數(shù)據(jù)?

Redis 的內(nèi)存淘汰策略只有在運行內(nèi)存達到了配置的最大內(nèi)存閾值時才會觸發(fā),這個閾值是通過redis.confmaxmemory參數(shù)來定義的。64 位操作系統(tǒng)下,maxmemory 默認為 0 ,表示不限制內(nèi)存大小。32 位操作系統(tǒng)下,默認的最大內(nèi)存值是 3GB。

你可以使用命令 config get maxmemory 來查看 maxmemory的值。

config get maxmemory
maxmemory
0

Redis 提供了 6 種內(nèi)存淘汰策略:

  • volatile-lru(least recently used):從已設置過期時間的數(shù)據(jù)集(server.db[i].expires)中挑選最近最少使用的數(shù)據(jù)淘汰。
  • volatile-ttl:從已設置過期時間的數(shù)據(jù)集(server.db[i].expires)中挑選將要過期的數(shù)據(jù)淘汰。
  • volatile-random:從已設置過期時間的數(shù)據(jù)集(server.db[i].expires)中任意選擇數(shù)據(jù)淘汰。
  • allkeys-lru(least recently used):從數(shù)據(jù)集(server.db[i].dict)中移除最近最少使用的數(shù)據(jù)淘汰。
  • allkeys-random:從數(shù)據(jù)集(server.db[i].dict)中任意選擇數(shù)據(jù)淘汰。
  • no-eviction(默認內(nèi)存淘汰策略):禁止驅(qū)逐數(shù)據(jù),當內(nèi)存不足以容納新寫入數(shù)據(jù)時,新寫入操作會報錯。

4.0 版本后增加以下兩種:

  • volatile-lfu(least frequently used):從已設置過期時間的數(shù)據(jù)集(server.db[i].expires)中挑選最不經(jīng)常使用的數(shù)據(jù)淘汰。
  • allkeys-lfu(least frequently used):從數(shù)據(jù)集(server.db[i].dict)中移除最不經(jīng)常使用的數(shù)據(jù)淘汰。

allkeys-xxx 表示從所有的鍵值中淘汰數(shù)據(jù),而 volatile-xxx 表示從設置了過期時間的鍵值中淘汰數(shù)據(jù)。

config.c中定義了內(nèi)存淘汰策略的枚舉數(shù)組:

configEnum maxmemory_policy_enum[] = {
    {"volatile-lru", MAXMEMORY_VOLATILE_LRU},
    {"volatile-lfu", MAXMEMORY_VOLATILE_LFU},
    {"volatile-random",MAXMEMORY_VOLATILE_RANDOM},
    {"volatile-ttl",MAXMEMORY_VOLATILE_TTL},
    {"allkeys-lru",MAXMEMORY_ALLKEYS_LRU},
    {"allkeys-lfu",MAXMEMORY_ALLKEYS_LFU},
    {"allkeys-random",MAXMEMORY_ALLKEYS_RANDOM},
    {"noeviction",MAXMEMORY_NO_EVICTION},
    {NULL, 0}
};

你可以使用 config get maxmemory-policy 命令來查看當前 Redis 的內(nèi)存淘汰策略。

> config get maxmemory-policy
maxmemory-policy
noeviction

可以通過config set maxmemory-policy 內(nèi)存淘汰策略 命令修改內(nèi)存淘汰策略,立即生效,但這種方式重啟 Redis 之后就失效了。修改 redis.conf 中的 maxmemory-policy 參數(shù)不會因為重啟而失效,不過,需要重啟之后修改才能生效。

maxmemory-policy noeviction

到此這篇關(guān)于深入理解Redis 內(nèi)存管理的文章就介紹到這了,更多相關(guān)Redis 內(nèi)存管理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • 深入解析Redisson分布式鎖看門狗機制

    深入解析Redisson分布式鎖看門狗機制

    本文主要介紹了深入解析Redisson分布式鎖看門狗機制,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2025-06-06
  • Redis獲取某個大key值的腳本實例

    Redis獲取某個大key值的腳本實例

    這篇文章主要給大家分享介紹了關(guān)于Redis獲取某個大key值的一個腳本實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。
    2018-04-04
  • 使用Grafana監(jiān)控Redis的操作方法

    使用Grafana監(jiān)控Redis的操作方法

    這篇文章主要介紹了使用Grafana監(jiān)控Redis,號稱下一代可視化監(jiān)控系統(tǒng),結(jié)合SpringBoot使用,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-04-04
  • Redis?中ZSET數(shù)據(jù)類型命令使用及對應場景總結(jié)(案例詳解)

    Redis?中ZSET數(shù)據(jù)類型命令使用及對應場景總結(jié)(案例詳解)

    這篇文章主要介紹了Redis?中ZSET數(shù)據(jù)類型命令使用及對應場景總結(jié),本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-01-01
  • redis的key出現(xiàn)的\xac\xed\x00\x05t\x00亂碼問題及解決

    redis的key出現(xiàn)的\xac\xed\x00\x05t\x00亂碼問題及解決

    這篇文章主要介紹了redis的key出現(xiàn)的\xac\xed\x00\x05t\x00亂碼問題及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • redis和hiredis的基本使用詳解

    redis和hiredis的基本使用詳解

    這篇文章主要介紹了redis和hiredis的基本使用,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-05-05
  • Redis主從同步配置的方法步驟(圖文)

    Redis主從同步配置的方法步驟(圖文)

    這篇文章主要介紹了Redis主從同步配置的方法步驟(圖文),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-02-02
  • Redis集群指定主從關(guān)系及動態(tài)增刪節(jié)點方式

    Redis集群指定主從關(guān)系及動態(tài)增刪節(jié)點方式

    這篇文章主要介紹了Redis集群指定主從關(guān)系及動態(tài)增刪節(jié)點方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • redis 交集、并集、差集的具體使用

    redis 交集、并集、差集的具體使用

    這篇文章主要介紹了redis 交集、并集、差集的具體使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-02-02
  • Redis核心知識點詳解及解析(附?Java?項目實踐案例)

    Redis核心知識點詳解及解析(附?Java?項目實踐案例)

    Redis是一款高性能的內(nèi)存鍵值數(shù)據(jù)庫,支持多種數(shù)據(jù)結(jié)構(gòu)和持久化機制,下面這篇文章主要介紹了Redis核心知識點及解析的相關(guān)資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2026-06-06

最新評論

灌南县| 辽阳县| 宜丰县| 比如县| 和林格尔县| 涟源市| 巴中市| 雅江县| 宁阳县| 黎平县| 扎鲁特旗| 石门县| 积石山| 牙克石市| 白沙| 灵川县| 邵东县| 三原县| 贺兰县| 商都县| 德兴市| 郎溪县| 拜城县| 文化| 门头沟区| 云浮市| 聊城市| 南丰县| 江口县| 甘孜县| 陈巴尔虎旗| 二连浩特市| 当涂县| 新沂市| 平遥县| 修水县| 久治县| 峨眉山市| 哈尔滨市| 石门县| 平果县|