1. 程式人生 > 其它 >這些Java高階必會知識點你能答出來幾個?內含福利

這些Java高階必會知識點你能答出來幾個?內含福利

這些Java高階必會知識點你能答出來幾個?內含福利

1、我往Redis裡寫的資料怎麼沒了?

使用Redis的同學你要明白一點,你為什麼用Redis?用redis的作用是什麼?用redis的好處是什麼?凡事多思考一下為什麼,多想想背後的原因。

就在不久前有朋友跟我說過,說他們生產環境的Redis怎麼經常會丟掉一些資料?寫進去了,過一會兒可能就沒了。我的天啊,你問這個問題就說明Redis你就沒用對啊。Redis是快取,你給當儲存了用了是吧?

首先要明白一點啥叫快取?為啥用快取?

Redis是用記憶體當快取的。記憶體是無限的嗎?相反,記憶體是很寶貴而且是有限的,磁碟是廉價而且是大量的。可能一臺機器就幾十個G的記憶體,但是可以有幾個T的硬碟空間。Redis主要是基於記憶體來進行高效能、高併發的讀寫操作的。

那既然記憶體是有限的,比如Redis就只能用10個G,你一直往裡面寫資料,一直寫一直寫最後10個G都用的差不多了,你還寫會,你想想會發生什麼?當然會幹掉一些的資料了,然後就保留10個G的資料。你說會不會造成資料丟失?

那Redis會幹掉哪些資料?保留哪些資料呢?當然是幹掉不常用的資料,保留常用的資料了。

所以說,這是快取的一個最基本的概念:資料是會過期的。要麼是你自己設定個過期時間,要麼是Redis自己給幹掉。

所以你的Redis如果使用不當,把生產資料存到裡面,又沒有去持久化到mysql,那就會有丟失的可能。

2、我的資料明明都過期了,怎麼還佔用著記憶體啊?

還有一種就是如果你給key設定好了一個過期時間,你知道到一定的時間再去查這個key就沒有了,但是你知道redis是怎麼給你弄成過期的嗎?什麼時候刪除掉?

如果你不知道,在實際的使用過程中你就可能會發現這麼一個問題:為啥好多資料明明應該過期了,結果發現redis記憶體佔用還是很高?那是因為你不知道Redis是怎麼刪除那些過期key的

舉例,Redis 記憶體一共是10個G,你現在往裡面寫了5個G的資料,然後你對這些資料全都設定了10分鐘之後過期,結果10分鐘之後,你再來檢視看,Redis的記憶體使用率怎麼還是50%呢?5個G的資料都過期了,我從redis裡查,是查不到了,結果過期的資料為啥還佔用著Redis的記憶體呢。

如果你連這個問題都不知道,上來就懵了,回答不出來,建議你使用Redis之前多做做功課,不然你寫程式碼的時候,想當然的認為寫進Redis的資料就一定會存在,後面導致系統各種漏洞和bug,就不好弄了。

3、問題剖析

(1)設定過期時間

set key value 過期時間(1小時)表示set進去的key,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如果設定成檢查所有Key那將是一場效能上的災難。所以實際上redis是每隔100ms隨機抽取一些key來檢查和刪除的。

但是問題是,隨機抽取檢測key是否過去會導致定期刪除策略可能會導致很多過期key到了時間並沒有被刪除掉,那咋整呢?所以Redis還有另一個策略就是惰性刪除

惰性刪除?就是說,在你獲取某個key的時候,Redis會檢查一下 ,這個key如果設定了過期時間那麼是否過期了?如果過期了此時就會刪除,不會給你返回任何東西。

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

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

那麼剛才的問題就不難理解了,就是說,你的過期key,靠定期刪除沒有被刪除掉,還停留在記憶體裡,佔用著你的記憶體呢,除非你的系統去查一下那個key,才會被redis給刪除掉。如果都過期了,定期刪除才刪了一點點,而你又沒有去查,沒有觸發惰性刪除,那麼短時間內你的redis記憶體佔用率還是會下不來。

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

別擔心Redis還有方案:記憶體淘汰機制。

(2)記憶體淘汰策略

如果Redis的記憶體佔用過多的時候,此時會進行記憶體淘汰,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記憶體淘汰策略,自動給你清理掉了一些最近很少使用的資料。

最後

在面試前我整理歸納了一些面試學習資料,文中結合我的朋友同學面試美團滴滴這類大廠的資料及案例
感興趣的朋友可以點選Java學習免費獲取。


由於篇幅限制,文件的詳解資料太全面,細節內容太多,所以只把部分知識點截圖出來粗略的介紹,每個小節點裡面都有更細化的內容!

大家看完有什麼不懂的可以在下方留言討論也可以關注。

覺得文章對你有幫助的話記得關注我點個贊支援一下!