善待Redis里的數據

jopen 9年前發布 | 32K 次閱讀 Redis NoSQL數據庫

Redis為我們提供便利的同時,我們也要善待里面的數據

</blockquote>

Redis是我們數據的保管者,我們可以隨時存隨時取,大的小的,重要的不重要的,它都毫無怨言的幫我們保存著,甚至有些時候,我們變得很懶,存東 西進去的時候順便還貼張紙:“過了一個星期就幫我扔了吧”,對于這些,Redis也都默默的接受了(誰叫Antirez把redis設計的這么好呢)。

這次要寫的就是關于這張留言紙的事。

Redis提供了一套“美好”的過期數據清理機制:

  • 主動過期: Redis對數據是惰性過期,當一個key到了過期時間,Redis也不會馬上清理,但如果這個key過期后被再次訪問,Redis就會主動將它清理掉。

    </li>

  • 被動過期: 如果過期的Key一直沒被訪問,Redis也不會一直把它放那不管,它會每秒10次的執行以下的清理工作:

    • 隨機從所有帶有過期時間的Key里取出20個
    • 如果發現有過期的,就清理
    • 如果這里有25%的Key都是過期的,就繼續回到第一步再來一次
    • </ul> </li> </ul>

      這套過期機制設計的很贊,可以這樣理解:如果當前有超過1/4的Key是過期的話,就不停地清理,直到只剩下1/4不到的Key是要過期的為止,然后就慢慢地隨機抽查著清理。

      現在我們再說說對待Redis數據的姿勢問題。

      先看一個現象,某段程序每天24小時的跑著,但時不時地出現拿不到連接的錯誤:

      Caused by: redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
      ...
      Caused by: java.util.NoSuchElementException: Unable to validate object

      這個錯誤是因為JedisPool拿到一個連接后,調用jedis.ping()方法沒有得到正確的返回”pong”消息,而出現這個問題時,并不是traffic的高峰期,redis的cpu不高,于是程序員很快就懷疑到網絡上,難道有”丟包”?

      但跑了幾天,發現出錯的時間固定在某幾個時間點(如晚上9點~10點),莫非是掃地阿姨每天定時在機房打掃衛生,碰著網線了?(有時候不得不佩服程序員的想象力)

      然而在一個夜黑風高的晚上,程序員的腦子在這個時候一般是最清醒的,這時告警短信又來了,打開redis監控,像在唯品會上逛街一樣,對著 redis的各項監控數據逛啊逛,突然,看到有幾條Expires的數據,當時的表情只能用看到關注了幾天的商品上標了大大”0.1折”時的表情來形容。

      接下來的事情,想必大家也都猜到個七七八八了,當然是下單搶購支付了,腦子里一系列的運算,掐指一算: “這個時間點正好有一大批key過期”,而且都是大的Set集合,每個都有幾十萬的數據,再一算: “Redis里的大部分需要過期的key就是這些key”。

      于是,答案有了,Redis進行被動過期清理時,發現怎么隨機,都有超過1/4的Key都是過期的,就忙著不停的刪啊刪,再加上又都是大集合的刪除,O(N)的操作復雜度,無奈,等redis刪完時,客戶端那邊的命令都等超時了。


      原因找到了,如何解決?看業務場景吧,對于我們的場景,做法是將過期時間設長一點,然后把這些可以刪掉的Key標記一下,丟到一個后臺線程那里分頁刪Set里的數據,這樣就算redis再做過期操作,也不會用太多的時間來刪除。

      最后,稍稍總結下,對于大個的集合對象,放redis的時候需要額外注意,如果想依賴redis的過期,可能會造成過期時短暫的redis block。

      所以,要善待redis數據,比如不用了就自己清理掉,不要等著redis來幫你。

      image

      來自:http://neway6655.github.io/redis/2015/12/19/善待Redis里的數據.html

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!