您好,登錄后才能下訂單哦!
這篇文章主要介紹了redis相關(guān)知識點及面試點有哪些的相關(guān)知識,內(nèi)容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇redis相關(guān)知識點及面試點有哪些文章都會有所收獲,下面我們一起來看看吧。
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è)置過期時間。
布隆過濾器:
輸入太白 進行三次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是一連串的二進制數(shù)字(0,1),每一位所在的位置為偏移(offset),在bitmap上可以執(zhí)行AND,OR,XOR以及其他操作。
位圖計數(shù)
位圖計數(shù)的意思是統(tǒng)計bitmap中值為1的位的個數(shù),位圖計數(shù)的效率是很高的。
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)前是否點贊過該照片,查詢是否點贊可以通過redis getbit操作來實現(xiàn)。比如查詢用戶id為1000的用戶是否點贊過照片id為100的照片,只需要對like_photo:100
bitmap的第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.}); |
比如需要顯示照片id為100的照片的獲贊次數(shù),只需要對like_photo:100
bitmap進行位圖計數(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ù)庫崩潰
解決方法 分布式鎖
99個請求過來的時候 先放行一個進去 此時在redis中沒有緩存 然后會新建一個 然后解鎖 這時候剩下的98個就可以讀到緩存了
緩存雪崩 大部分緩存失效 或者redis崩潰了
解決辦法 搭建高可用集群 或者過期時間錯開
如何保持數(shù)據(jù)庫與緩存一致性
redis和mysql數(shù)據(jù)一致性的問題
在這里,我們討論三種更新策略:
先更新緩存,再更新數(shù)據(jù)庫
先更新數(shù)據(jù)庫,再更新緩存
先刪除緩存,再更新數(shù)據(jù)庫
先更新數(shù)據(jù)庫,再刪除緩存
問題:更新緩存成功,更新數(shù)據(jù)庫失敗,導(dǎo)致數(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ù)庫后,都再次計算寫入緩存的值,無疑是浪費性能的。顯然,刪除緩存更為適合。
問題:
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ù)庫是一致的。
問題:上面C的查詢,已經(jīng)說明問題了。
出現(xiàn)數(shù)據(jù)不一致的概率,比較小。采取這個方案,取決于業(yè)務(wù)需求。
真正靠譜的方案:將訪問操作串行化
先刪緩存,將更新數(shù)據(jù)庫的操作放進有序隊列中
從緩存查不到的查詢操作,都進入有序隊列
需要解決的問題:
讀請求積壓,大量超時,導(dǎo)致數(shù)據(jù)庫的壓力:限流、熔斷
如何避免大量請求積壓:將隊列水平拆分,提高并行度。
保證相同請求路由正確。
關(guān)于“redis相關(guān)知識點及面試點有哪些”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對“redis相關(guān)知識點及面試點有哪些”知識都有一定的了解,大家如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(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)容。