您现在的位置是:Instagram刷粉絲, Ins買粉絲自助下單平台, Ins買贊網站可微信支付寶付款 > 

01 redis消息訂閱與發布數據丟失(redis會在一段時間內丟失數據,為什么)

Instagram刷粉絲, Ins買粉絲自助下單平台, Ins買贊網站可微信支付寶付款2024-04-29 10:10:21【】8人已围观

简介redis會在一段時間內丟失數據,為什么檢查一下是不是內存不夠用了,內存不夠用的話redis會進行內存回收的,具體策略如下:volatile-lru:從已設置過期時間的數據集(server.db[i]

redis會在一段時間內丟失數據,為什么

檢查一下是不是內存不夠用了,內存不夠用的話redis會進行內存回收的,具體策略如下:

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(驅逐):禁止驅逐數據

Redis數據丟失問題

之前有朋友問過我,說我們生產環境的redis怎么經常會丟掉一些數據?寫進去了,過一會兒可能就沒了。

我的天啊,你問這個問題就說明redis你就沒用對啊。redis是緩存,你給當存儲了是吧?

啥叫緩存?用內存當緩存。內存是無限的嗎?恰恰相反,內存是很寶貴而且是有限的,磁盤是廉價而且是大量的。可能一臺機器就幾十個G的內存,但是可以有幾個T的硬盤空間。redis主要是基于內存來進行高性能、高并發的讀寫操作的。

那既然內存是有限的,比如redis就只能用10個G,你要是往里面寫了20個G的數據,會咋辦?當然會干掉10個G的數據,然后就保留10個G的數據了。那干掉哪些數據?保留哪些數據?當然是干掉不常用的數據,保留常用的數據了。

所以說,這是緩存的一個最基本的概念,數據是會過期的,要么是你自己設置個過期時間,要么是redis自己給干掉。

例如:set key value 過期時間(1小時)

set進去的key,1小時之后就沒了,就失效了

(1)設置過期時間

我們set key的時候,都可以給一個expire time,就是過期時間,指定這個key比如說只能存活1個小時?10分鐘?這個很有用,我們自己可以指定緩存到期就失效。

如果假設你設置一批key只能存活1個小時,那么接下來1小時后,redis是怎么對這批key進行刪除的?

答案是:定期刪除+惰性刪除

所謂定期刪除,指的是redis默認是每隔100ms就隨機抽取一些設置了過期時間的key,檢查其是否過期,如果過期就刪除。

假設redis里放了10萬個key,都設置了過期時間,你每隔幾百毫秒,就檢查10萬個key,那redis基本上就死了,cpu負載會很高的,消耗在你的檢查過期key上了。

注意,這里可不是每隔100ms就遍歷所有的設置過期時間的key,那樣就是一場性能上的災難。實際上redis是每隔100ms隨機抽取一些key來檢查和刪除的。

但是問題是,定期刪除可能會導致很多過期key到了時間并沒有被刪除掉,那咋整呢?所以就是惰性刪除了。惰性刪除就是說,在你獲取某個key的時候,redis會檢查一下 ,這個key如果設置了過期時間那么是否過期了?如果過期了此時就會刪除,不會給你返回任何東西。

所以并不是key到時間就被刪除掉,而是你查詢這個key的時候,redis再懶惰的檢查一下。

通過上述兩種手段,保證過期的key一定會被干掉。

很簡單,就是說,你的過期key,靠定期刪除沒有被刪除掉,還停留在內存里,占用著你的內存呢,除非你的系統去查一下那個key,才會被redis給刪除掉。

但是實際上這還是有問題的,如果定期刪除漏掉了很多過期key,然后你也沒及時去查,也就沒走惰性刪除,此時會怎么樣?如果大量過期key堆積在內存里,導致redis內存塊耗盡了,咋整?

答案是:走內存淘汰機制。

(2)內存淘汰

如果redis的內存占用過多的時候,此時會進行內存淘汰,有如下一些策略:

1)noeviction:當內存不足以容納新寫入數據時,新寫入操作會報錯,這個一般沒人用吧,實在是太惡心了

2)allkeys-lru:當內存不足以容納新寫入數據時,在鍵空間中,移除最近最少使用的key(這個是最常用的)

3)allkeys-random:當內存不足以容納新寫入數據時,在鍵空間中,隨機移除某個key,這個一般沒人用吧,為啥要隨機,肯定是把最近最少使用的key給干掉啊

4)volatile-lru:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,移除最近最少使用的key(這個一般不太合適)

5)volatile-random:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,隨機移除某個key

6)volatile-ttl:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,有更早過期時間的key優先移除

例如:redis 里有10個key,現在內存已經滿了,設置的淘汰策略是allkeys-lru,redis需要刪除掉一些key來保證你可以繼續寫入。在這10個key中,其中1個key,最近1分鐘被查詢了100次,1個key,最近10分鐘被查詢了50次,1個key,最近1個小時被查詢了1次。肯定那些最近最少使用的被干掉了。

為啥存redis的數據有時候會丟失?

很簡單,你寫的數據太多了,內存占滿了,或者觸發了什么條件,如redis allkeys-lru內存淘汰策略,自動給你清理掉了一些最近很少使用的數據。

Redis主從復制丟失數據的情況分析

1.主備切換的過程,可能會導致數據丟失

因為master -> slave的復制是異步的,所以可能有部分數據還沒復制到slave,master就宕機了,此時這些部分數據就丟失了

2.腦裂導致的數據丟失

腦裂,也就是說,某個master所在機器突然脫離了正常的網絡,跟其他slave機器不能連接,但是實際上master還運行著,此時哨兵可能就會認為master宕機了,然后開啟選舉,將其他slave切換成了master,這個時候,集群里就會有兩個master,也就是所謂的腦裂,此時雖然某個slave被切換成了master,但是可能client還沒來得及切換到新的master,還繼續向舊master寫數據,此時有可能也丟失了,因此舊master再次恢復的時候,會被作為一個slave掛到新的master上去,自己的數據會清空,重新從新的master復制數據

減少數據丟失的配置:

min-slaves-to-write 1

min-slaves-max-lag 10

要求至少有1個slave,數據復制和同步的延遲不能超過10秒,如果說一旦所有的slave,數據復制和同步的延遲都超過了10秒鐘,那么這個時候,master就不會再接收任何請求了

有了min-slaves-max-lag這個配置,就可以確保說,一旦slave復制數據和ack延時太長,就認為可能master宕機后損失的數據太多了,那么就拒絕寫請求,這樣可以把master宕機時由于部分數據未同步到slave導致的數據丟失降低到可控范圍內

  如果一個master出現了腦裂,跟其它的slave丟失連接,那么這兩個配置可以確保,如果不能繼續給指定數量的slave發送數據,而且slave超過10秒沒有給自己ack消息,那么就直接拒絕客戶端的寫請求,這樣腦裂后的舊master就不會接受client的新數據,也就避免了數據丟失,因此在腦裂場景下,最多就丟失10秒的數據

在此我向大家推薦一個架構學習交流群。交流學習群號:938837867 暗號:555 里面會分享一些資深架構師錄制的視頻錄像:有Spring,MyBatis,Netty源碼分析,高并發、高性能、分布式、微服務架構的原理,JVM性能優化、分布式架構等這些成為架構師必備

很赞哦!(73)

Instagram刷粉絲, Ins買粉絲自助下單平台, Ins買贊網站可微信支付寶付款的名片

职业:程序员,设计师

现居:广东揭阳惠来县

工作室:小组

Email:[email protected]