天天看點

Redis學習筆記---Redis的緩存過期和淘汰政策

Redis學習筆記—Redis的緩存過期和淘汰政策

1.性能簡介

  1. Redis性能高:
  2. 官方資料
  3. 讀:110000次/s
  4. 寫:81000次/s
  5. 長期使用,key會不斷增加,Redis作為緩存使用,實體記憶體也會滿
  6. 記憶體與硬碟交換(swap) 虛拟記憶體 ,頻繁IO 性能急劇下降

2.maxmemory:作為redis最大實體記憶體

  1. 不設定的場景,作為DB使用

    1. Redis的key是固定的,不會增加
    2. Redis作為DB使用,保證資料的完整性,不能淘汰 , 可以做叢集,橫向擴充
    3. 緩存淘汰政策:禁止驅逐 (預設)
  2. 設定的場景

    1. Redis是作為緩存使用,不斷增加Key
    2. maxmemory : 預設為0 不限制
  3. 問題

    :達到實體記憶體後性能急劇下架,甚至崩潰,這是為什麼?

    :記憶體與硬碟交換(swap) 虛拟記憶體 ,頻繁IO 性能急劇下降
  4. 設定多少?

    1. 與業務有關
    2. 1個Redis執行個體,保證系統運作 1 G ,剩下的就都可以設定Redis,實體記憶體的3/4
    3. slaver : 留出一定的記憶體
    4. 在redis.conf 設定屬性

      maxmemory 1024mb

      ,如果數字後面沒有機關一律按照B結尾
  5. 指令

    : 獲得maxmemory數 `CONFIG GET maxmemory
  6. 設定maxmemory後,當趨近maxmemory時,通過緩存淘汰政策,從記憶體中删除對象
  7. 不設定maxmemory 無最大記憶體限制 maxmemory-policy noeviction (禁止驅逐) 不淘汰
  8. 設定maxmemory,在配置檔案中maxmemory-policy(淘汰政策) 要配置

3. expire資料結構

  1. Redis

    中可以使用

    expire

    指令設定一個鍵的存活時間

    (ttl: time to live)

    ,過了這段時間,該鍵就會自動被删除。

4.expire原理

Redis學習筆記---Redis的緩存過期和淘汰政策
  1. 上面的代碼是Redis 中關于資料庫的結構體定義,這個結構體定義中除了 id 以外都是指向字典的指針,其中我們隻看 dict 和 expires。
  2. dict 用來維護一個 Redis 資料庫中包含的所有 Key-Value 鍵值對,expires則用于維護一個 Redis 資料庫中設定了失效時間的鍵(即key與失效時間的映射)。
  3. 當我們使用 expire指令設定一個key的失效時間時,Redis 首先到 dict 這個字典表中查找要設定的key是否存在,如果存在就将這個key和失效時間添加到 expires 這個字典表。
  4. 當我們使用 setex指令向系統插入資料時,Redis 首先将 Key 和 Value 添加到 dict 這個字典表中,然後将 Key 和失效時間添加到 expires 這個字典表中。
  5. 簡單地總結來說就是,設定了失效時間的key和具體的失效時間全部都維護在 expires 這個字典表中。

5.删除政策

  1. Redis的資料删除有定時删除、惰性删除和主動删除三種方式。
  2. Redis目前采用惰性删除+主動删除的方式。
  3. 定時删除
    1. 在設定鍵的過期時間的同時,建立一個定時器,讓定時器在鍵的過期時間來臨時,立即執行對鍵的删除操作。
    2. 需要建立定時器,而且消耗CPU,一般不推薦使用。
  4. 惰性删除
    1. 在key被通路時如果發現它已經失效,那麼就删除它。
    2. 調用expireIfNeeded函數,該函數的意義是:讀取資料之前先檢查一下它有沒有失效,如果失效了就删除它。
  5. 主動删除
    1. 在redis.conf檔案中可以配置主動删除政策,預設是no-enviction(不删除)
    2. 在redis.conf檔案中可以配置

      maxmemory-policy allkeys-lru

6.LRU簡介

  1. LRU (Least recently used) 最近最少使用,算法根據資料的曆史通路記錄來進行淘汰資料,其核心思想是“如果資料最近被通路過,那麼将來被通路的幾率也更高”。
  2. 最常見的實作是使用一個連結清單儲存緩存資料,詳細算法實作如下:
    1. 新資料插入到連結清單頭部;
    2. 每當緩存命中(即緩存資料被通路),則将資料移到連結清單頭部;
    3. 當連結清單滿的時候,将連結清單尾部的資料丢棄。
    4. 在Java中可以使用LinkHashMap(哈希連結清單)去實作LRU
  3. 讓我們以使用者資訊的需求為例,來示範一下LRU算法的基本思路:
    1. 假設我們使用哈希連結清單來緩存使用者資訊,目前緩存了4個使用者,這4個使用者是按照時間順序依次從連結清單右端插入的。

7.LRU資料淘汰機制

  1. 在伺服器配置中儲存了 lru 計數器 server.lrulock,會定時(redis 定時程式 serverCorn())更新,server.lrulock 的值是根據 server.unixtime 計算出來的。
  2. 另外,從redisObject 中可以發現,每一個 redis 對象都會設定相應的 lru。可以想象的是,每一次通路資料的時候,會更新 redisObject.lru。
  3. LRU 資料淘汰機制是這樣的:在資料集中随機挑選幾個鍵值對,取出其中 lru 最大的鍵值對淘汰。
  4. 不可能周遊key 用

    目前時間-最近通路

    越大 說明 通路間隔時間越長

8. 緩存淘汰政策的選擇

  1. noeviction

    : 不删除政策, 達到最大記憶體限制時, 如果需要更多記憶體, 直接傳回錯誤資訊。 大多數寫指令都會導緻占用更多的記憶體(有極少數會例外, 如 DEL )。
  2. allkeys-lru

    : 所有key通用; 優先删除最近最少使用(less recently used ,LRU) 的 key,在不确定時一般采用政策。 冷熱資料交換
  3. volatile-lru

    : 隻限于設定了 expire 的部分; 優先删除最近最少使用(less recently used ,LRU) 的 key,比allkeys-lru性能差,存過期時間
  4. allkeys-random

    : 希望請求符合平均分布(每個元素以相同的機率被通路)
  5. volatile-random

    : 隻限于設定了 expire 的部分; 随機删除一部分 key。
  6. volatile-ttl

    :自己控制,隻限于設定了 expire 的部分; 優先删除剩餘時間(time to live,TTL) 短的key,緩存穿透

繼續閱讀