為什么使用Redis
項(xiàng)目中使用Redis,主要考慮性能和并發(fā)。如果僅僅是分布式鎖這些,完全可以用中間件ZooKeeper等代替。
性能:
如下圖所示,在大并發(fā)的情況下,所有的請(qǐng)求直接訪問數(shù)據(jù)庫,數(shù)據(jù)庫會(huì)出現(xiàn)連接異常。這個(gè)時(shí)候,就需要使用Redis做一個(gè)緩沖操作,讓請(qǐng)求先訪問到Redis,而不是直接訪問數(shù)據(jù)庫。
根據(jù)交互效果的不同,響應(yīng)時(shí)間沒有固定標(biāo)準(zhǔn)。在理想狀態(tài)下,我們的頁面跳轉(zhuǎn)需要在瞬間解決,對(duì)于頁內(nèi)操作則需要在剎那間解決。
并發(fā):
如下圖所示,在大并發(fā)的情況下,所有的請(qǐng)求直接訪問數(shù)據(jù)庫,數(shù)據(jù)庫會(huì)出現(xiàn)連接異常。這個(gè)時(shí)候,就需要使用Redis做一個(gè)緩沖操作,讓請(qǐng)求先訪問到Redis,而不是直接訪問數(shù)據(jù)庫。
2、使用Redis有什么缺點(diǎn)?
緩存和數(shù)據(jù)庫雙寫一致性問題
緩存雪崩問題
緩存擊穿問題
緩存的并發(fā)競(jìng)爭(zhēng)問題
3、單線程的Redis為什么這么快?
你知道Redis是單線程工作模型嗎?
純內(nèi)存操作
單線程操作,避免了頻繁的上下文切換
采用了非阻塞I/O多路復(fù)用機(jī)制
4、Redis的數(shù)據(jù)類型及使用場(chǎng)景
(這5種類型你用到過幾個(gè)?)
String:一般做一些復(fù)雜的計(jì)數(shù)功能的緩存;
Hash:單點(diǎn)登錄;
List:做簡(jiǎn)單的消息隊(duì)列的功能;
Set:做全局去重的功能;
SortedSet:做排行榜應(yīng)用,取TOPN操作;延時(shí)任務(wù);做范圍查找。
5、Redis過期策略和內(nèi)存淘汰機(jī)制?
正解:Redis采用的是定期刪除+惰性刪除策略。
為什么不用定時(shí)刪除策略?定期刪除+惰性刪除是如何工作的呢?采用定期刪除+惰性刪除就沒其他問題了么?
6、Redis和數(shù)據(jù)庫雙寫一致性問題
(最終一致性和強(qiáng)一致性)
如果對(duì)數(shù)據(jù)有強(qiáng)一致性要求,不能放緩存。
7、如何應(yīng)對(duì)緩存穿透和緩存雪崩問題
緩存穿透:即黑客故意去請(qǐng)求緩存中不存在的數(shù)據(jù),導(dǎo)致所有的請(qǐng)求都懟到數(shù)據(jù)庫上,從而數(shù)據(jù)庫連接異常。
緩存雪崩:即緩存同一時(shí)間大面積的失效,這個(gè)時(shí)候又來了一波請(qǐng)求,結(jié)果請(qǐng)求都懟到數(shù)據(jù)庫上,從而導(dǎo)致數(shù)據(jù)庫連接異常。
中小型的公司一般遇不到這些問題,但是大并發(fā)的項(xiàng)目,流量有幾百萬左右,這兩個(gè)問題一定要深刻考慮。
8、如何解決Redis并發(fā)競(jìng)爭(zhēng)Key問題?
這個(gè)問題大致就是,同時(shí)有多個(gè)子系統(tǒng)去set一個(gè)key。不太推薦使用redis的事務(wù)機(jī)制。
(1)如果對(duì)這個(gè)key操作,不要求順序
這種情況下,準(zhǔn)備一個(gè)分布式鎖,大家去搶鎖,搶到鎖就做set操作即可。
(2)如果對(duì)這個(gè)key操作,要求順序
假設(shè)有一個(gè)key1,系統(tǒng)A需要將key1設(shè)置為valueA,系統(tǒng)B需要將key1設(shè)置為valueB,系統(tǒng)C需要將key1設(shè)置為valueC.
期望按照key1的value值按照 valueA-->valueB-->valueC的順序變化。這種時(shí)候我們?cè)跀?shù)據(jù)寫入數(shù)據(jù)庫的時(shí)候,需要保存一個(gè)時(shí)間戳。假設(shè)時(shí)間戳如下
系統(tǒng)A key 1 {valueA 3:00}
系統(tǒng)B key 1 {valueB 3:05}
系統(tǒng)C key 1 {valueC 3:10}
那么,假設(shè)這會(huì)系統(tǒng)B先搶到鎖,將key1設(shè)置為{valueB 3:05}。接下來系統(tǒng)A搶到鎖,發(fā)現(xiàn)自己的valueA的時(shí)間戳早于緩存中的時(shí)間戳,那就不做set操作了。以此類推。
其他方法,比如利用隊(duì)列,將set方法變成串行訪問也可以??傊?,靈活變通。