溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

redis相關(guān)知識點及面試點有哪些

發(fā)布時間:2022-01-15 15:58:11 來源:億速云 閱讀:150 作者:iii 欄目:大數(shù)據(jù)

這篇文章主要介紹了redis相關(guān)知識點及面試點有哪些的相關(guān)知識,內(nèi)容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇redis相關(guān)知識點及面試點有哪些文章都會有所收獲,下面我們一起來看看吧。

四、Redis為什么這么快

1、完全基于內(nèi)存,絕大部分請求是純粹的內(nèi)存操作,非??焖?。數(shù)據(jù)存在內(nèi)存中,類似于HashMap,HashMap的優(yōu)勢就是查找和操作的時間復(fù)雜度都是O(1);

2、數(shù)據(jù)結(jié)構(gòu)簡單,對數(shù)據(jù)操作也簡單,Redis中的數(shù)據(jù)結(jié)構(gòu)是專門進行設(shè)計的;

3、采用單線程,避免了不必要的上下文切換和競爭條件,也不存在多進程或者多線程導(dǎo)致的切換而消耗 CPU,不用去考慮各種鎖的問題,不存在加鎖釋放鎖操作,沒有因為可能出現(xiàn)死鎖而導(dǎo)致的性能消耗;

4、使用多路I/O復(fù)用模型,非阻塞IO;

5、使用底層模型不同,它們之間底層實現(xiàn)方式以及與客戶端之間通信的應(yīng)用協(xié)議不一樣,Redis直接自己構(gòu)建了VM 機制 ,因為一般的系統(tǒng)調(diào)用系統(tǒng)函數(shù)的話,會浪費一定的時間去移動和請求;

以上幾點都比較好理解,下邊我們針對多路 I/O 復(fù)用模型進行簡單的探討:

(1)多路 I/O 復(fù)用模型

多路I/O復(fù)用模型是利用 select、poll、epoll 可以同時監(jiān)察多個流的 I/O 事件的能力,在空閑的時候,會把當(dāng)前線程阻塞掉,當(dāng)有一個或多個流有 I/O 事件時,就從阻塞態(tài)中喚醒,于是程序就會輪詢一遍所有的流(epoll 是只輪詢那些真正發(fā)出了事件的流),并且只依次順序的處理就緒的流,這種做法就避免了大量的無用操作。

這里“多路”指的是多個網(wǎng)絡(luò)連接,“復(fù)用”指的是復(fù)用同一個線程。采用多路 I/O 復(fù)用技術(shù)可以讓單個線程高效的處理多個連接請求(盡量減少網(wǎng)絡(luò) IO 的時間消耗),且 Redis 在內(nèi)存中操作數(shù)據(jù)的速度非???,也就是說內(nèi)存內(nèi)的操作不會成為影響Redis性能的瓶頸,主要由以上幾點造就了 Redis 具有很高的吞吐量。

緩存穿透:緩存當(dāng)中沒有 數(shù)據(jù)庫當(dāng)中也沒有

解決方法:緩存空對象 布隆過濾器

緩存空對象:如果redis中沒有,數(shù)據(jù)庫中也沒查到,就在redis中填加一個這個key對應(yīng)的空對象。下次判斷的時候 如果在redis中查到這個空對象,就說明查詢不到數(shù)據(jù)。缺點:會創(chuàng)造大量的空對象,并且還要設(shè)置過期時間。

布隆過濾器:

redis相關(guān)知識點及面試點有哪些

輸入太白  進行三次hash 將得到的值標記為1 其他的以此類推 等以后找的時候也是三次hash 能找到就是可能存在 有一個找不到就是絕對不存在

如果你輸入一個不存在的 但是三次hash都為1 還是可能存在的  這時候就屬于誤觸了

誤觸率跟hash次數(shù)和長度有關(guān)  布隆過濾器缺點:需要維護 ;不能刪除

redis底層保存的數(shù)據(jù)是位數(shù)組

點贊需求以及使用redis的解決思路。第一種點贊需求是比較常規(guī)的點贊需求,類似于微博那種點贊模式,用戶可以對某條信息點贊、取消點贊、查詢是否點贊、被點贊次數(shù)等等;第二種點贊稍微特殊,用戶可以在一天內(nèi)對任意用戶點贊,取消點贊后不可以再次對同用戶點贊,第二天限制解除,可以重新對同一玩家點贊(也就是說點贊是可以累加的),然后還有一個需求是要求可以實時查用戶獲贊次數(shù)全局的排行情況。

需求一解決思路

對于需求一,采用的是redis bitmap來實現(xiàn)。

bitmap簡介

bitmap

bitmap是一連串的二進制數(shù)字(0,1),每一位所在的位置為偏移(offset),在bitmap上可以執(zhí)行AND,OR,XOR以及其他操作。

位圖計數(shù)

位圖計數(shù)的意思是統(tǒng)計bitmap中值為1的位的個數(shù),位圖計數(shù)的效率是很高的。

redis bitmap

redis中允許使用二進制的Key和二進制的Value,bitmap就是二進制的Value。

點贊/取消點贊

假設(shè)用戶的數(shù)字id為1000,對照片id為100的照片點贊。首先根據(jù)照片id生成贊數(shù)據(jù)存儲的redis key,比如生成策略為like_photo:{photo_id},id為1000的用戶點贊,只需要將like_photo:100的第1000位置為1即可(取消贊則置為0)。

redis setbit操作的時間復(fù)雜度為O(1),所以這種點贊方式十分高效。

123
redis.setbit('like_photo:100', 1000, 1, function(err, ret){    // deal err and ret.});
當(dāng)前是否點贊

用戶打開圖片的時候需要查詢當(dāng)前是否點贊過該照片,查詢是否點贊可以通過redis getbit操作來實現(xiàn)。比如查詢用戶id為1000的用戶是否點贊過照片id為100的照片,只需要對like_photo:100bitmap的第1000位取值即可。

redis getbit操作的時間復(fù)雜度同樣是O(1)。

1234
redis.getbit('like_photo:100', 1000, function(err, liked){    // deal err.    // if liked==1 liked, liked==0 not like yet.});
查詢點贊總次數(shù)

比如需要顯示照片id為100的照片的獲贊次數(shù),只需要對like_photo:100bitmap進行位圖計數(shù)操作即可。

redis bitcount操作的時間復(fù)雜度雖然是O(N)的,但是大部分數(shù)據(jù)量的情況下是不需要擔(dān)心bitcount效率問題的。

123
redis.bitcount('like_photo:100', function(err, likeCnt){    // deal with err and likeCnt.});

緩存擊穿:數(shù)據(jù)庫有數(shù)據(jù) 但是緩存中沒數(shù)據(jù)或者緩存的數(shù)據(jù)恰好失效的時候 突然大量的訪問過來  此時會訪問數(shù)據(jù)造成數(shù)據(jù)庫崩潰

解決方法  分布式鎖

redis相關(guān)知識點及面試點有哪些

99個請求過來的時候  先放行一個進去   此時在redis中沒有緩存 然后會新建一個  然后解鎖 這時候剩下的98個就可以讀到緩存了

緩存雪崩  大部分緩存失效 或者redis崩潰了

解決辦法 搭建高可用集群 或者過期時間錯開

如何保持數(shù)據(jù)庫與緩存一致性

redis和mysql數(shù)據(jù)一致性的問題

在這里,我們討論三種更新策略:

  1. 先更新緩存,再更新數(shù)據(jù)庫

  2. 先更新數(shù)據(jù)庫,再更新緩存

  3. 先刪除緩存,再更新數(shù)據(jù)庫

  4. 先更新數(shù)據(jù)庫,再刪除緩存

第一種,先更新緩存,再更新數(shù)據(jù)庫

問題:更新緩存成功,更新數(shù)據(jù)庫失敗,導(dǎo)致數(shù)據(jù)不一致。

第二種,先更新數(shù)據(jù)庫,再更新緩存

問題:

1、A更新數(shù)據(jù)庫

2、B更新數(shù)據(jù)庫

3、B寫入緩存

4、A寫入緩存

出現(xiàn)數(shù)據(jù)不一致。

考慮另一種情況, 有如下兩點:
(1)如果你是一個寫數(shù)據(jù)庫場景比較多,而讀數(shù)據(jù)場景比較少的業(yè)務(wù)需求,采用這種方案就會導(dǎo)致,數(shù)據(jù)壓根還沒讀到,緩存就被頻繁的更新,浪費性能。
(2)如果你寫入數(shù)據(jù)庫的值,并不是直接寫入緩存的,而是要經(jīng)過一系列復(fù)雜的計算再寫入緩存。那么,每次寫入數(shù)據(jù)庫后,都再次計算寫入緩存的值,無疑是浪費性能的。顯然,刪除緩存更為適合。

第三種,先刪除緩存,再更新數(shù)據(jù)庫。

問題:

1、A刪除緩存

2、B查詢數(shù)據(jù)庫獲取舊值

3、B更新了緩存

4、A更新數(shù)據(jù)庫

出現(xiàn)數(shù)據(jù)不一致的問題

延時雙刪

public void write(String key,Object data){
	redis.delKey(key);
	db.updateData(data);
	Thread.sleep(1000);
	redis.delKey(key);
}

問題一:延時雙刪,演變成了:先更新數(shù)據(jù)庫,再刪除緩存。。。。

比如:

1、A刪除緩存

2、B查詢數(shù)據(jù)庫獲取舊值

3、B更新了緩存

4、A更新數(shù)據(jù)庫

5、A延時刪緩存

1~3步執(zhí)行后,數(shù)據(jù)庫和緩存是一致的,相當(dāng)于沒刪除。

4~5步:先更新數(shù)據(jù)庫,再刪緩存。

所以延時雙刪演變成了:先更新數(shù)據(jù)庫,再刪除緩存。問題還是沒解決。。。

為什么?假設(shè),此時,在第4步執(zhí)行之前,又來了個查詢C,C查詢到舊值。第6步:C將舊值插入緩存。此時出現(xiàn)緩存和數(shù)據(jù)庫不一致。

延時并不能解決:C插入緩存的操作在第5步后面執(zhí)行,比如C遇到網(wǎng)絡(luò)問題、GC問題等。當(dāng)然這是小概率,但并不代表不存在。

當(dāng)然,延時越長,這個問題越能規(guī)避。如果業(yè)務(wù)需求不是非常嚴格,是可以忽略的。

問題二:吞吐量

問題三:數(shù)據(jù)庫更新后,無法保證下一次查詢,從緩存獲取的值和數(shù)據(jù)庫是一致的。

第四種,先更新數(shù)據(jù)庫,再刪除緩存

問題:上面C的查詢,已經(jīng)說明問題了。

出現(xiàn)數(shù)據(jù)不一致的概率,比較小。采取這個方案,取決于業(yè)務(wù)需求。

終極方案

請求串行化

真正靠譜的方案:將訪問操作串行化

  1. 先刪緩存,將更新數(shù)據(jù)庫的操作放進有序隊列中

  2. 從緩存查不到的查詢操作,都進入有序隊列

需要解決的問題:

  1. 讀請求積壓,大量超時,導(dǎo)致數(shù)據(jù)庫的壓力:限流、熔斷

  2. 如何避免大量請求積壓:將隊列水平拆分,提高并行度。

  3. 保證相同請求路由正確。

關(guān)于“redis相關(guān)知識點及面試點有哪些”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對“redis相關(guān)知識點及面試點有哪些”知識都有一定的了解,大家如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI