<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          聊聊Redis面試題

          共 3136字,需瀏覽 7分鐘

           ·

          2022-02-20 03:46

          大家好,許久不見,我是Leo。

          最近抽了一部分時(shí)間在BOOS上解答了一些面試題,點(diǎn)贊量和Get 數(shù)挺多的。這篇文章就聊一些Redis的一些面試題。

          什么是Redis的緩存預(yù)熱?

          緩存預(yù)熱主要是雙十一流量比較大的業(yè)務(wù)場(chǎng)景。為了提升用戶的訪問性能,減少一開始缺少緩存Key到數(shù)據(jù)庫查詢數(shù)據(jù)的慢性能問題。一般會(huì)采用系統(tǒng)上線前把熱點(diǎn)緩存預(yù)熱到redis中。這樣用戶就不用一開始去數(shù)據(jù)庫查了,直接Redis內(nèi)存返給你了。

          單線程性能為什么優(yōu)于多線程?

          一個(gè)CPU在運(yùn)行多個(gè)線程時(shí),會(huì)存在多線程調(diào)用的消耗問題,而且還有多個(gè)線程調(diào)用時(shí)數(shù)據(jù)一致性的問題。這些都要單獨(dú)處理,單獨(dú)處理又會(huì)消耗性能。于是Redis統(tǒng)籌兼顧采用了單,多線程并用的思路。

          在處理數(shù)據(jù)寫入,讀取屬于鍵值對(duì)數(shù)據(jù)操作,采用單線程操作。在請(qǐng)求連接,從socket中讀取請(qǐng)求,解析客戶端發(fā)送請(qǐng)求,采用多線程操作

          Redis巧妙的把所有需要延遲等待的操作全部轉(zhuǎn)交給了多線程處理,在不需要等待的全部單線程處理。個(gè)人感覺這種設(shè)計(jì)思路很棒

          多路復(fù)用機(jī)制

          IO多路復(fù)用機(jī)制是指一個(gè)線程處理多個(gè)IO流,也是我們經(jīng)常聽到的select/epoll機(jī)制。那么那些連接,等待的操作Redis都是如何處理的呢?

          在Redis只運(yùn)行單線程的情況下,同一時(shí)間存在多個(gè)監(jiān)聽套接字,和已連接的套接字,內(nèi)核會(huì)一直監(jiān)聽這些連接請(qǐng)求和數(shù)據(jù)請(qǐng)求。一旦客戶端發(fā)送請(qǐng)求就會(huì)以事件的方式通知Redis主線程處理。這就是Redis線程處理多個(gè)IO流的效果。

          上文說到以事件方式通知Redis這里我們做一個(gè)擴(kuò)展,select/epoll提供了基于事件的回調(diào)機(jī)制,不同的事件會(huì)調(diào)用相應(yīng)的處理函數(shù)。一旦請(qǐng)求來了,立刻加到事件隊(duì)列中,Redis單線程就會(huì)源源不斷的處理該事件隊(duì)列。解決了等待與掃描的資源浪費(fèi)問題。

          Redis中如何解決緩存的一致性問題

          很多人一上來就是加鎖,這樣的回答顯然不是面試官想看到的,我們可以搭一個(gè)知識(shí)樹。比如可以這樣回答。

          Redis緩存分為兩種?讀寫緩存?和?只讀緩存?。不同的緩存類型會(huì)引發(fā)不同的問題。

          對(duì)于讀寫緩存來說,讀壓力和寫壓力都來源于一個(gè)庫,如果對(duì)數(shù)據(jù)發(fā)生了修改。我們除了要考慮數(shù)據(jù)庫的一致性以外,還要考慮緩存中的數(shù)據(jù)一致性。

          這里可以展開聊一下寫壓力的寫回策略

          • 當(dāng)采用同步直寫策略,寫緩存時(shí),可以保證緩存與數(shù)據(jù)庫的數(shù)據(jù)一致性。
          • 當(dāng)采用異步寫回策略,寫緩存時(shí),由于是異步執(zhí)行,無法保證命令都執(zhí)行也就是無法保證數(shù)據(jù)一致性。

          上述策略如何選擇主要看業(yè)務(wù)的需求了,如果核心數(shù)據(jù),一定不能錯(cuò)的數(shù)據(jù),我們可以同步直寫再搭配事務(wù)機(jī)制。如果不是特別重要的數(shù)據(jù),那我們就可以采用異步寫回策略來提升性能。

          對(duì)于只讀緩存來說,會(huì)有一個(gè)子庫,專門提供讀服務(wù),但是如果有新數(shù)據(jù)進(jìn)來,子庫必須跟著主庫進(jìn)行數(shù)據(jù)同步,來保證主從庫的數(shù)據(jù)一致性。

          這里可以展開聊一下 Redis,MySQL的原子性是怎么保證的

          • 如果先刪緩存,后更新數(shù)據(jù)庫:緩存刪除成功,數(shù)據(jù)更新失敗,導(dǎo)致用戶向緩存讀數(shù)據(jù)時(shí),沒有發(fā)現(xiàn)緩存key就會(huì)打向數(shù)據(jù)庫,而數(shù)據(jù)庫數(shù)據(jù)沒有更新成功導(dǎo)致讀到舊值
          • 如果先更新數(shù)據(jù)庫,后刪緩存:?更新數(shù)據(jù)庫成功時(shí),緩存刪除失敗,就會(huì)導(dǎo)致數(shù)據(jù)庫保留了最新的值,用戶向Redis讀數(shù)據(jù)時(shí),發(fā)現(xiàn)緩存key存在,直接返回了就拿到了上一個(gè)舊值。

          會(huì)發(fā)現(xiàn)上述都不能保證,這里為什么我還要提呢?告訴面試官你是經(jīng)過很多思考的,別搞的跟背答案似的。

          解決方案

          可以采用重試機(jī)制,比如用Redis的List當(dāng)消息隊(duì)列,或者采用MQ消息隊(duì)列來處理。

          不管是?先刪緩存,后更新數(shù)據(jù)庫?還是?先更新數(shù)據(jù)庫后刪緩存?一旦失敗就會(huì)出現(xiàn)兩邊不一致的情況,那我們就可以采用MQ消費(fèi)機(jī)制,只有當(dāng)兩種情況全部成功,才把MQ這條數(shù)據(jù)刪掉,要不然就重復(fù)消費(fèi)。也就是重新再執(zhí)行一遍。

          這里擴(kuò)展一下,我們?cè)趫?zhí)行重復(fù)消費(fèi)的那一刻,如果有數(shù)據(jù)打過來怎么辦?

          所以我們?cè)诮鉀Q時(shí),一般會(huì)給他sleep一小段時(shí)間再進(jìn)行緩存操作。這樣就會(huì)避免這種那一刻的誤差。

          Redis為什么要設(shè)置隨機(jī)過期時(shí)間

          Redis設(shè)置的過期時(shí)間問題,如果很多key在同一時(shí)刻大面積過期,會(huì)影響Redis的性能。

          Redis是使用單線程讀寫數(shù)據(jù)的,大面積過期會(huì)阻塞Redis的處理效率。所以,在應(yīng)用Redis的key時(shí)要避免兩種情況,bigkey?和?大面積過期key

          對(duì)于第二種情況,我們只要設(shè)置一個(gè)隨機(jī)過期時(shí)間就不會(huì)存在大面積過期啦。

          這里還可以跟面試官聊一下Redis的過期刪除策略和過期的刪除機(jī)制。因?yàn)樯衔牡膭h除key的依據(jù)是來源于過期策略和刪除機(jī)制的。

          過期刪除機(jī)制

          過期刪除機(jī)制是Redis用來回收內(nèi)存空間的常用機(jī)制,可以對(duì)鍵值對(duì)設(shè)置過期時(shí)間,默認(rèn)情況下,Redis每100毫秒就會(huì)刪除一些過期的key,具體算法如下:

          • 采樣 ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP 個(gè)數(shù)的 key,并將其中過期的 key 全部刪除;
          • 如果超過 25% 的 key 過期了,則重復(fù)刪除的過程,直到過期 key 的比例降至 25% 以下。

          ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP 默認(rèn)為20。毫秒的概念可能不太明顯,我們換算一下也就是每秒刪除200個(gè)過期key(20個(gè)/100毫秒)=(200個(gè)/秒)

          如果按照第一種的話,并不是造成太大的影響。如果命中了第二種,就會(huì)造成key大面積失效過期,過期的key超過了25%,會(huì)一直刪除直至降至25%。這段刪除期間會(huì)大量釋放內(nèi)存空間,大量插入鏈表填補(bǔ)。Redis就變慢了。

          過期刪除策略

          這個(gè)應(yīng)該是比較簡(jiǎn)單的

          • 定時(shí)刪除:采用定時(shí)器方式,時(shí)間一到就刪
          • 惰性刪除:惰性刪除并不是當(dāng)?shù)竭_(dá)過期時(shí)間去刪除,而是每次獲取鍵值時(shí),會(huì)判斷是否過期,如果過期就刪,并返回空。沒過期就返回鍵值
          • 定期刪除:每隔一段時(shí)間,就對(duì)數(shù)據(jù)庫中的鍵進(jìn)行檢查,如果過期則刪除。至于要?jiǎng)h除多少什么時(shí)候刪除則是通過具體程序決定的

          定時(shí)刪除策略

          優(yōu)點(diǎn)是:對(duì)內(nèi)存友好。因?yàn)橥ㄟ^定時(shí)器,當(dāng)一個(gè)鍵到達(dá)過期時(shí)間時(shí)就會(huì)立馬被刪除,直接就釋放了內(nèi)存。

          缺點(diǎn)是:對(duì) CPU 不友好。因?yàn)槿绻^期鍵比較多,那么刪除這些過期鍵會(huì)占用相當(dāng)一部分 CPU 時(shí)間,如果 CPU 時(shí)間非常緊張的話,還將 CPU 時(shí)間用在刪除和當(dāng)前任務(wù)無關(guān)的過期鍵上,會(huì)對(duì)服務(wù)器的響應(yīng)時(shí)間以及吞吐量造成影響。

          因此,通過 定時(shí)刪除 策略對(duì)過期鍵的刪除不太現(xiàn)實(shí)。

          惰性刪除

          優(yōu)點(diǎn):對(duì) CPU 時(shí)間友好。程序只會(huì)在取出鍵時(shí)才會(huì)判斷是否刪除,并且只作用到當(dāng)前鍵上,其他過期鍵不會(huì)花費(fèi) CPU 時(shí)間去處理。

          缺點(diǎn):對(duì)內(nèi)存不友好。因?yàn)橹挥墟I被使用時(shí)才會(huì)去檢查是否刪除,如果有大量的鍵一直不被使用,那么這些鍵就算過期了也不會(huì)被刪除,會(huì)一直占用著內(nèi)存。這種可以理解為是一種內(nèi)存泄漏——大量無用的數(shù)據(jù)一直占用著內(nèi)存,并且不會(huì)被刪除。

          定期刪除

          相比較定時(shí)刪除對(duì) CPU 的不友好,惰性刪除的對(duì)內(nèi)存不友好。定期刪除采用了一種折中的方式:

          定期刪除策略每隔一段時(shí)間執(zhí)行一次刪除過期鍵操作,并通過限制刪除操作執(zhí)行的時(shí)長(zhǎng)和頻率來減少刪除操作對(duì) CPU 時(shí)間的影響。并且,通過定期刪除過期鍵,有效的減少了過期鍵帶來的內(nèi)存浪費(fèi)。但刪除的時(shí)長(zhǎng)和頻率比較難定義,

          因?yàn)椋喝绻l率太高或者時(shí)長(zhǎng)太長(zhǎng),那么會(huì)占用大量的 CPU 時(shí)長(zhǎng)。如果過短又會(huì)出現(xiàn)內(nèi)存浪費(fèi)的情況。

          因此。如果采用定期刪除策略的話需要通過具體的業(yè)務(wù)場(chǎng)景來定義時(shí)長(zhǎng)和頻率。


          瀏覽 60
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  大鸡吧插逼视频 | 欧美黑人操逼网站 | 国产一级a毛一级a看免费人交 | 五月婷婷在线视频 | 操逼免费网 |