天天看點

Redis(二十):Redis資料過期和淘汰政策詳解(轉)

原文位址:https://yq.aliyun.com/articles/257459#

背景

Redis作為一個高性能的記憶體NoSQL資料庫,其容量受到最大記憶體限制的限制。

使用者在使用Redis時,除了對性能,穩定性有很高的要求外,對記憶體占用也比較敏感。在使用過程中,有些使用者會覺得自己的線上執行個體記憶體占用比自己預想的要大。

事實上,執行個體中的記憶體除了儲存原始的鍵值對所需的開銷外,還有一些運作時産生的額外記憶體,包括:

  1. 垃圾資料和過期Key所占空間
  2. 字典漸進式Rehash導緻未及時删除的空間
  3. Redis管理資料,包括底層資料結構開銷,用戶端資訊,讀寫緩沖區等
  4. 主從複制,bgsave時的額外開銷
  5. 其它

本文主要分析第一項Redis過期政策對記憶體的影響。

設定過期時間

  • expire key time(以秒為機關)--這是最常用的方式
  • setex(String key, int seconds, String value)–字元串獨有的方式

注意:

  • 除了字元串自己獨有設定過期時間的方法外,其他方法都需要依靠expire方法來設定時間
  • 如果沒有設定時間,那緩存就是永不過期
  • 如果設定了過期時間,之後又想讓緩存永不過期,使用persist key

Redis三種Key過期政策

    1、被動删除(惰性删除)

  當讀/寫一個已經過期的key時,會觸發惰性删除政策,直接删除掉這個過期key。

  隻有key被操作時(如GET),REDIS才會被動檢查該key是否過期,如果過期則删除之并且傳回NIL。

    a.這種删除政策對CPU是友好的,删除操作隻有在不得不的情況下才會進行,不會其他的expire key上浪費無謂的CPU時間。

    b.但是這種政策對記憶體不友好,一個key已經過期,但是在它被操作之前不會被删除,仍然占據記憶體空間。如果有大量的過期鍵存在但是又很少被通路到,那會造成大量的記憶體空間浪費。expireIfNeeded(redisDb *db, robj *key)函數位于src/db.c。

  但僅是這樣是不夠的,因為可能存在一些key永遠不會被再次通路到,這些設定了過期時間的key也是需要在過期後被删除的,我們甚至可以将這種情況看作是一種記憶體洩露----無用的垃圾資料占用了大量的記憶體,而伺服器卻不會自己去釋放它們,這對于運作狀态非常依賴于記憶體的Redis伺服器來說,肯定不是一個好消息

  優點:删除操作隻發生在從資料庫取出key的時候發生,而且隻删除目前key,是以對CPU時間的占用是比較少的,而且此時的删除是已經到了非做不可的地步(如果此時還不删除的話,我們就會擷取到了已經過期的key了)

  缺點:若大量的key在超出逾時時間後,很久一段時間内,都沒有被擷取過,那麼可能發生記憶體洩露(無用的垃圾占用了大量的記憶體)

    2、主動删除

  由于惰性删除政策無法保證冷資料被及時删掉,是以Redis會定期主動淘汰一批已過期的key。

  先說一下時間事件,對于持續運作的伺服器來說, 伺服器需要定期對自身的資源和狀态進行必要的檢查和整理, 進而讓伺服器維持在一個健康穩定的狀态, 這類操作被統稱為正常操作(cron job)。在 Redis 中, 正常操作由 

redis.c/serverCron

 實作。

  優點:通過限制删除操作的時長和頻率,來減少删除操作對CPU時間的占用–處理"定時删除"的缺點,定期删除過期key–處理"惰性删除"的缺點。

    3、maxmemory

  • volatile-lru:從已設定過期時間的資料集(server.db[i].expires)中挑選最近最少使用 的資料淘汰
  • volatile-ttl:從已設定過期時間的資料集(server.db[i].expires)中挑選将要過期的數 據淘汰
  • volatile-random:從已設定過期時間的資料集(server.db[i].expires)中任意選擇資料 淘汰
  • allkeys-lru:從資料集(server.db[i].dict)中挑選最近最少使用的資料淘汰
  • allkeys-random:從資料集(server.db[i].dict)中任意選擇資料淘汰
  • no-enviction(驅逐):(預設)禁止驅逐資料

相關最佳實踐優化配置

    • 不要放垃圾資料,及時清理無用資料

      實驗性的資料和下線的業務資料及時删除;

    • key盡量都設定過期時間

      對具有時效性的key設定過期時間,通過redis自身的過期key清理政策來降低過期key對于記憶體的占用,同時也能夠減少業務的麻煩,不需要定期手動清理了.

    • 單Key不要過大

      給使用者排查問題時遇到過單個string的value有43M的,也有一個list 100多萬個大成員占了1G多記憶體的。這種key在get的時候網絡傳輸延遲會比較大,需要配置設定的輸出緩沖區也比較大,在定期清理的時候也容易造成比較高的延遲. 最好能通過業務拆分,資料壓縮等方式避免這種過大的key的産生。

    • 不同業務如果公用一個業務的話,最好使用不同的邏輯db分開

      從上面的分析可以看出,Redis的過期Key清理政策和強制淘汰政策都會周遊各個db。将key分布在不同的db有助于過期Key的及時清理。另外不同業務使用不同db也有助于問題排查和無用資料的及時下線.

繼續閱讀