中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

公司就兩個(gè)開(kāi)發(fā)百度seo教程網(wǎng)

公司就兩個(gè)開(kāi)發(fā),百度seo教程網(wǎng),單位建設(shè)一個(gè)網(wǎng)站的費(fèi)用,做素材網(wǎng)站賺錢(qián)嗎說(shuō)在前面 在40歲老架構(gòu)師尼恩的(50)讀者社區(qū)中,經(jīng)常有小伙伴,需要面試美團(tuán)、京東、阿里、 百度、頭條等大廠(chǎng)。 下面是一個(gè)5年小伙伴成功拿到通過(guò)了京東一面面試,并且最終拿到offer,月薪40K。 現(xiàn)在把面試…

說(shuō)在前面

在40歲老架構(gòu)師尼恩的(50+)讀者社區(qū)中,經(jīng)常有小伙伴,需要面試美團(tuán)、京東、阿里、 百度、頭條等大廠(chǎng)。

下面是一個(gè)5年小伙伴成功拿到通過(guò)了京東一面面試,并且最終拿到offer,月薪40K。

現(xiàn)在把面試真題和參考答案收入咱們的寶典,大家看看,收個(gè)優(yōu)質(zhì)Offer需要學(xué)點(diǎn)啥?

當(dāng)然對(duì)于中高級(jí)開(kāi)發(fā)來(lái)說(shuō),這些面試題,也有參考意義。

小伙伴說(shuō),光代碼漂亮不夠, 面試,還得會(huì)吹。

這里把題目以及小伙伴的吹牛逼的方式方法,經(jīng)過(guò)整理和梳理之后,收入咱們的《尼恩Java面試寶典》 V95版本,供后面的小伙伴參考,提升大家的 3高 架構(gòu)、設(shè)計(jì)、開(kāi)發(fā)、吹牛水平。

《尼恩 架構(gòu)筆記》《尼恩高并發(fā)三部曲》《尼恩Java面試寶典》的PDF,請(qǐng)到公號(hào)【技術(shù)自由圈】取

文章目錄

    • 說(shuō)在前面
    • 京東一面
      • 1、說(shuō)一說(shuō) JVM內(nèi)存模型
        • JVM內(nèi)存結(jié)構(gòu)
        • Java內(nèi)存模型圖
      • 2、CMS和G1有什么區(qū)別? 什么時(shí)候發(fā)生垃圾回收? 然后,說(shuō)說(shuō)大致的回收過(guò)程?
        • 完整的GC流程
        • 什么時(shí)候發(fā)生垃圾回收
        • 對(duì)象存活判斷方法
        • 垃圾回收算法
      • 3、對(duì)于數(shù)據(jù)的一致性是怎么保證的?
      • 4、Redis集群有沒(méi)有了解過(guò),主從和選舉是怎樣的?
        • 一、Redis高可用集群架構(gòu)
        • 二、主從數(shù)據(jù)同步
        • 三、選主機(jī)制
        • 四、過(guò)期內(nèi)存淘汰策略
      • 5、看你們公司使用的是MySQL,你們使用的是哪種存儲(chǔ)引擎,為什么?MyISAM和InnoDB的區(qū)別
      • 6、mysql索引的底層數(shù)據(jù)結(jié)構(gòu)是什么,為什么選擇這種數(shù)據(jù)結(jié)構(gòu)
      • 7、說(shuō)說(shuō)什么情況下索引失效
      • 8、手寫(xiě)代碼:設(shè)計(jì)一個(gè)分布式自增id生成服務(wù)
      • 9、有沒(méi)有了解過(guò)網(wǎng)絡(luò)安全問(wèn)題,常見(jiàn)的網(wǎng)絡(luò)攻擊有哪些,原理是什么,可以怎么解決
        • 一、XSS 跨站腳本攻擊
        • 二、CSRF 跨站請(qǐng)求偽造
        • 三、DDoS 分布式拒絕服務(wù)攻擊
        • 四、SQL 注入
      • 10、平時(shí)在開(kāi)發(fā)接口或者設(shè)計(jì)項(xiàng)目的時(shí)候如何保證安全性的
      • 11、使用Redis集群時(shí)可能會(huì)存在什么問(wèn)題
        • 一、數(shù)據(jù)一致性問(wèn)題
        • 二、性能問(wèn)題
        • 三、可用性問(wèn)題
        • 四、負(fù)載均衡問(wèn)題
        • 五、網(wǎng)絡(luò)延遲問(wèn)題
        • 六、節(jié)點(diǎn)故障問(wèn)題
        • 七、安全問(wèn)題
      • 12、有沒(méi)有了解過(guò)cap和base原則
        • 一、CAP理論
        • 二、BASE 理論
      • 13、zk是如何保證一致性的
        • 一:ZAB協(xié)議(Zookeeper原子消息廣播協(xié)議)
        • 二、選主
        • 三、選主后的數(shù)據(jù)同步
        • 四、事務(wù)操作
      • 14、你如何設(shè)計(jì)一個(gè)能抗住大流量的系統(tǒng),說(shuō)說(shuō)設(shè)計(jì)方案
      • 15、有沒(méi)有了解過(guò)緩存策略有哪些
        • 一、Cache Aside(旁路緩存)策略
        • 二、Read/Write Through(讀穿 / 寫(xiě)穿)策略
        • 三、Write Back(寫(xiě)回)策略
        • 總結(jié)
    • 參考文獻(xiàn)
    • 尼恩說(shuō)在最后

京東一面

1、說(shuō)一說(shuō) JVM內(nèi)存模型

小伙伴從以下2個(gè)維度去 “吹牛”, 吹到 面試官 “口水直流,不能自已”

  • 第一個(gè)維度:JVM內(nèi)存結(jié)構(gòu)
  • 第二個(gè)維度:Java內(nèi)存模型圖

JVM內(nèi)存結(jié)構(gòu)

程序計(jì)數(shù)器:當(dāng)前線(xiàn)程所執(zhí)行的字節(jié)碼的行號(hào)指示器,用于記錄正在執(zhí)行的虛擬機(jī)字節(jié)指令地址,線(xiàn)程私有。

Java虛擬棧:存放基本數(shù)據(jù)類(lèi)型、對(duì)象的引用、方法出口等,線(xiàn)程私有。

Native方法棧:和虛擬棧相似,只不過(guò)它服務(wù)于Native方法,線(xiàn)程私有。

Java堆:java內(nèi)存最大的一塊,所有對(duì)象實(shí)例、數(shù)組都存放在java堆,GC回收的地方,線(xiàn)程共享。

方法區(qū):存放已被加載的類(lèi)信息、常量、靜態(tài)變量、即時(shí)編譯器編譯后的代碼數(shù)據(jù)等。(即永久帶),回收目標(biāo)主要是常量池的回收和類(lèi)型的卸載,各線(xiàn)程共享

Java內(nèi)存模型圖

Java內(nèi)存模型規(guī)定了所有的變量都存儲(chǔ)在主內(nèi)存中,每條線(xiàn)程還有自己的工作內(nèi)存,線(xiàn)程的工作內(nèi)存中保存了該線(xiàn)程中是用到的變量的主內(nèi)存副本拷貝,線(xiàn)程對(duì)變量的所有操作都必須在工作內(nèi)存中進(jìn)行,而不能直接讀寫(xiě)主內(nèi)存。不同的線(xiàn)程之間也無(wú)法直接訪(fǎng)問(wèn)對(duì)方工作內(nèi)存中的變量,線(xiàn)程間變量的傳遞均需要自己的工作內(nèi)存和主存之間進(jìn)行數(shù)據(jù)同步進(jìn)行。

尼恩說(shuō)明:

由于篇幅限制,這里對(duì)JVM內(nèi)存結(jié)構(gòu)、Java內(nèi)存模式的介紹,沒(méi)有做展開(kāi),

有關(guān)JVM內(nèi)存結(jié)構(gòu)、Java內(nèi)存模式的詳細(xì)介紹,可以參考《尼恩Java面試寶典》中JVM面試專(zhuān)題的內(nèi)存模型部分

2、CMS和G1有什么區(qū)別? 什么時(shí)候發(fā)生垃圾回收? 然后,說(shuō)說(shuō)大致的回收過(guò)程?

小伙伴從以下6個(gè)維度去 “吹?!?#xff0c; 吹到 面試官 “口水直流,不能自已”

  • 首先,說(shuō)說(shuō)垃圾回收的本質(zhì)
  • 其次,CMS和G1有什么區(qū)別
  • 再次:完整的GC流程
  • 再次: 什么時(shí)候發(fā)生垃圾回收
  • 再次:對(duì)象存活判斷方法
  • 最后:垃圾回收算法

垃圾回收的本質(zhì)

垃圾回收是Java程序執(zhí)行自動(dòng)內(nèi)存管理的過(guò)程。當(dāng)Java程序在JVM上運(yùn)行時(shí),將在堆上創(chuàng)建對(duì)象,這是專(zhuān)用于該程序的內(nèi)存的一部分。最終,將不再需要某些對(duì)象。垃圾收集器找到這些未使用的對(duì)象并將其刪除以釋放內(nèi)存。

CMS和G1有什么區(qū)別

CMS(Concurrent Mark Sweep)收集器(標(biāo)記-清除算法): 老年代并行收集器,以獲取最短回收停頓時(shí)間為目標(biāo)的收集器,具有高并發(fā)、低停頓的特點(diǎn),追求最短GC回收停頓時(shí)間。

G1(Garbage First)收集器(標(biāo)記-整理算法): Java堆并行收集器,G1收集器是JDK1.7提供的一個(gè)新收集器,G1收集器基于“標(biāo)記-整理”算法實(shí)現(xiàn),也就是說(shuō)不會(huì)產(chǎn)生內(nèi)存碎片。此外,G1收集器不同于之前的收集器的一個(gè)重要特點(diǎn)是:G1回收的范圍是整個(gè)Java堆(包括新生代,老年代),而前六種收集器回收的范圍僅限于新生代或老年代。

區(qū)別:

  • CMS收集器是老年代的收集器,可以配合新生代的Serial和ParNew收集器一起使用;
  • G1收集器收集范圍是老年代和新生代,不需要結(jié)合其他收集器使用;
  • CMS收集器以最小的停頓時(shí)間為目標(biāo)的收集器;
  • G1收集器可預(yù)測(cè)垃圾回收的停頓時(shí)間
  • CMS收集器是使用“標(biāo)記-清除”算法進(jìn)行的垃圾回收,容易產(chǎn)生內(nèi)存碎片
  • G1收集器使用的是“標(biāo)記-整理”算法,進(jìn)行了空間整合,降低了內(nèi)存空間碎片。

完整的GC流程

在JVM中一次完整的GC流程如下:

  1. 標(biāo)記垃圾對(duì)象;
  2. 清除垃圾對(duì)象;
  3. 將存活的對(duì)象復(fù)制到另一個(gè)區(qū)域;
  4. 清空原區(qū)域。

JVM中的垃圾回收分為三個(gè)階段:Minor GC、Full GC和G1 GC。

  • Minor GC,是針對(duì)新生代的垃圾回收器,主要清理Eden區(qū)和Survivor區(qū)的垃圾;
  • Full GC,是對(duì)整個(gè)堆空間進(jìn)行垃圾回收,包括新生代和老年代;
  • G1 GC,是一種基于Region的垃圾回收器,它將堆空間劃分為不同的Region,每個(gè)Region都有一個(gè)根節(jié)點(diǎn),當(dāng)某個(gè)Region的大小達(dá)到一定閾值時(shí),就會(huì)觸發(fā)一次GC。

什么時(shí)候發(fā)生垃圾回收

當(dāng)對(duì)象對(duì)當(dāng)前使用這個(gè)對(duì)象的應(yīng)用程序變得不可觸及的時(shí)候,這個(gè)對(duì)象就可以被回收了。

垃圾回收不會(huì)發(fā)生在永久代,如果永久代滿(mǎn)了或者是超過(guò)了臨界值,會(huì)觸發(fā)完全垃圾回收(Full GC)。

如果你仔細(xì)查看垃圾收集器的輸出信息,就會(huì)發(fā)現(xiàn)永久代也是被回收的。這就是為什么正確的永久代大小對(duì)避免Full GC是非常重要的原因。

對(duì)象存活判斷方法

Java中判斷對(duì)象存活的方法有以下兩種算法:

  1. 引用計(jì)數(shù)算法:給對(duì)象添加一個(gè)引用計(jì)數(shù)器,每當(dāng)有一個(gè)地方引用它時(shí),計(jì)數(shù)器值就+1;當(dāng)引用失效時(shí),計(jì)數(shù)器值就-1;任何時(shí)刻計(jì)數(shù)器為0的對(duì)象就是不可能再被使用的對(duì)象。這種算法雖然簡(jiǎn)單,但是有個(gè)致命的缺點(diǎn),就是不能適用于相互引用的情況。
  2. 可達(dá)性分析算法:通過(guò)從根對(duì)象開(kāi)始向下搜索,直到找到一個(gè)無(wú)法直接或間接訪(fǎng)問(wèn)到的對(duì)象為止。這個(gè)過(guò)程稱(chēng)為“可達(dá)性分析”,如果一個(gè)對(duì)象不可達(dá),則說(shuō)明它已經(jīng)不再使用,可以被回收。

垃圾回收算法

Java中常見(jiàn)的三種垃圾收集算法是標(biāo)記-清除算法(Mark-Sweep)、復(fù)制算法(Copying)和分代收集算法(Generational Collection)。

  1. 標(biāo)記-清除算法:這種算法首先會(huì)標(biāo)記出所有活動(dòng)對(duì)象,然后將它們從內(nèi)存中移除。接下來(lái),算法會(huì)遍歷整個(gè)堆空間,將未被標(biāo)記的對(duì)象進(jìn)行回收。這種算法的缺點(diǎn)是會(huì)產(chǎn)生內(nèi)存碎片。
  2. 復(fù)制算法:這種算法將堆空間分為兩個(gè)區(qū)域:Eden區(qū)和Survivor區(qū)。新創(chuàng)建的對(duì)象首先分配到Eden區(qū)中,然后經(jīng)過(guò)多次復(fù)制和清除后才會(huì)被移動(dòng)到Survivor區(qū)中。當(dāng)Survivor區(qū)空間不足時(shí),就會(huì)觸發(fā)一次Full GC來(lái)進(jìn)行垃圾回收。這種算法的優(yōu)點(diǎn)是可以避免內(nèi)存碎片。
  3. 分代收集算法:這種算法將堆空間分為三個(gè)區(qū)域:新生代、老年代和永久代。新生代又分為Eden區(qū)、Survivor區(qū)和From區(qū)。這種算法的優(yōu)點(diǎn)是可以更好地利用CPU緩存,提高程序運(yùn)行效率。

3、對(duì)于數(shù)據(jù)的一致性是怎么保證的?

小伙伴說(shuō),他是參考《尼恩Java面試寶典》中 Redis 專(zhuān)題中的數(shù)據(jù)一致性問(wèn)題及方案去吹的, 面試官非常滿(mǎn)意

4、Redis集群有沒(méi)有了解過(guò),主從和選舉是怎樣的?

小伙伴從以下7個(gè)維度去 “吹牛”, 吹到 面試官 “口水直流,不能自已”

  • 首先,說(shuō)說(shuō)Redis高可用集群架構(gòu)
    • 兩個(gè)小的維度一,主從哨兵模式
    • 兩個(gè)小的維度二,Cluster集群模式
  • 再次:說(shuō)說(shuō)兩種主從數(shù)據(jù)同步方式
    • 兩個(gè)小的維度一,全量復(fù)制
    • 兩個(gè)小的維度二,增量復(fù)制
  • 第三:說(shuō)說(shuō)說(shuō)說(shuō)兩種選主機(jī)制
    • 兩個(gè)小的維度一,主從哨兵模式選主
    • 兩個(gè)小的維度二,Cluster集群模式選主
  • 最后,嘚瑟一下過(guò)期內(nèi)存淘汰策略

一、Redis高可用集群架構(gòu)

Redis高可用集群有兩種,分別是主從哨兵模式和集群模式

1.主從哨兵模式

其中一臺(tái)服務(wù)器作為master服務(wù)器,提供讀寫(xiě)服務(wù),配置多臺(tái)從服務(wù)器,從服務(wù)器只提供只讀服務(wù),同時(shí)配置多臺(tái)sentinel,也即是哨兵,哨兵的作用是可以監(jiān)控master節(jié)點(diǎn),如果master宕機(jī),可以從從服務(wù)器中選舉出一臺(tái)作為master服務(wù)器。

哨兵模式,客戶(hù)端連接哨兵集群,即可獲得master服務(wù)器的信息。此時(shí)客戶(hù)端并不會(huì)做讀寫(xiě)分離,也就是所有讀寫(xiě)都由master服務(wù)器處理,這里相當(dāng)于從服務(wù)器只作為主服務(wù)器的數(shù)據(jù)備份。如果master發(fā)生故障,切換到其他從服務(wù)器,哨兵會(huì)把新的master服務(wù)器地址告知客戶(hù)端。

jedis和RedisTemplate都沒(méi)有實(shí)現(xiàn)讀寫(xiě)分離。如果需要可以分別建立master服務(wù)器連接池和slave服務(wù)器連接池,并嚴(yán)格區(qū)分讀寫(xiě)操作,路由到需要使用的連接池。需要注意的是,Redis主從復(fù)制是異步的,可能存在小概率數(shù)據(jù)不一致的問(wèn)題。

2.Cluster集群模式

在主從哨兵模式,所有的寫(xiě)操作都是由master處理,這在性能上可能會(huì)出現(xiàn)瓶頸。Redis3.0后推出了集群模式,可以實(shí)現(xiàn)水平擴(kuò)展,配置多臺(tái)的master服務(wù)器處理讀寫(xiě)請(qǐng)求。

集群模式下,看似于將一個(gè)大的主從架構(gòu)拆分成多個(gè)主從架構(gòu)的服務(wù)器群,具有復(fù)制,高可用和分片的特性。不需要哨兵,也可以實(shí)現(xiàn)節(jié)點(diǎn)故障移除和master選舉功能。性能和高可用性均優(yōu)于哨兵模式,但需要更多的服務(wù)器。可以從公司業(yè)務(wù)的并發(fā)量和成本等角度考量選擇哪種模式。

Redis Cluster集群模式默認(rèn)將所有的數(shù)據(jù)劃分為16384個(gè)slot槽,每個(gè)master節(jié)點(diǎn)均勻負(fù)責(zé)一部的槽位。

通常,會(huì)對(duì)key值使用crc16算法進(jìn)行hash得到一個(gè)整數(shù)值,然后使用這個(gè)整數(shù)值對(duì)16384進(jìn)行取模,來(lái)得到具體的槽位。

Cluster集群模式下,Redis默認(rèn)從服務(wù)是不分擔(dān)讀請(qǐng)求,只作為備注和故障轉(zhuǎn)移。但有讀請(qǐng)求到達(dá)從服務(wù)器,會(huì)重定向到主服務(wù)器處理。

二、主從數(shù)據(jù)同步

Redis主從數(shù)據(jù)同步大致分為兩種,全量復(fù)制和增量復(fù)制

全量復(fù)制

增量復(fù)制

一般情況下,主從斷開(kāi)連接后會(huì)進(jìn)行全量復(fù)制,但Redis2.8后開(kāi)始支持部分?jǐn)?shù)據(jù)的復(fù)制。

master和從服務(wù)器第一次連接時(shí)會(huì)進(jìn)行全量復(fù)制,同時(shí)master和所有的slave都會(huì)維護(hù)一個(gè)復(fù)制數(shù)據(jù)的偏移量offset和master的進(jìn)程id。

如果從服務(wù)器斷開(kāi)重連后,會(huì)比較偏移量是否太舊或者master進(jìn)程id是否變更了,如果這樣則會(huì)進(jìn)行一次全量復(fù)制,否則會(huì)進(jìn)行部分復(fù)制,把offset之后的數(shù)據(jù)同步給從服務(wù)器。

三、選主機(jī)制

1.主從哨兵模式

這種模式下,是有哨兵監(jiān)控master服務(wù)器狀態(tài),并實(shí)現(xiàn)故障轉(zhuǎn)移。一旦master服務(wù)器宕機(jī),則哨兵會(huì)從剩下的從服務(wù)器中選舉一條作為新的master節(jié)點(diǎn)。這里有幾個(gè)概念:

主觀(guān)下線(xiàn):

哨兵會(huì)定期向主服務(wù)器發(fā)送心跳包檢測(cè)是否正常,如果超過(guò)配置文件中sentinel down-after-milliseconds mymaster 配置的時(shí)間沒(méi)有收到主服務(wù)器的回復(fù),則這個(gè)哨兵認(rèn)為主服務(wù)下線(xiàn)。

客觀(guān)下線(xiàn):

一個(gè)哨兵把master記為主觀(guān)下線(xiàn),并不代表master就一定下線(xiàn)了,此時(shí)要向其他哨兵確認(rèn)master是否真的下線(xiàn),如果超過(guò)sentinel monitor mymaster 配置的數(shù)量(一般為哨兵數(shù)量/2 + 1)哨兵認(rèn)為master下線(xiàn),則記為客觀(guān)下線(xiàn)。

哨兵選舉master服務(wù)器過(guò)程:

  1. 先從哨兵中選舉出一個(gè)leader,并由這個(gè)leader選舉出新的master
  2. 過(guò)濾故障節(jié)點(diǎn),從剩余的節(jié)點(diǎn)中按照下列規(guī)則選出master
  3. 優(yōu)先選擇slave-priority最大的從節(jié)點(diǎn)作為主節(jié)點(diǎn)
  4. 其次選擇數(shù)據(jù)偏移量最大的節(jié)點(diǎn)
  5. 選擇runid最小的從節(jié)點(diǎn)

2.集群模式

  1. slave發(fā)現(xiàn)自己的master下線(xiàn)后,會(huì)廣播故障轉(zhuǎn)移信息到其他master節(jié)點(diǎn)
  2. master接收到slave故障轉(zhuǎn)移請(qǐng)求后,首先會(huì)檢測(cè)請(qǐng)求的合法性,然后發(fā)送響應(yīng)ack給slave,每輪投票,master只會(huì)響應(yīng)一次
  3. 一旦一個(gè)slave接收超過(guò)半數(shù)master的ack后,則被選中成為新的master,否則會(huì)進(jìn)行下一輪的投票

四、過(guò)期內(nèi)存淘汰策略

  1. 被動(dòng)刪除,客戶(hù)端get 請(qǐng)求某個(gè)key時(shí),會(huì)判斷是否過(guò)期,如果過(guò)期了,則會(huì)清楚
  2. 主動(dòng)刪除,redis定期掃描一批key,檢查是否過(guò)期,如果過(guò)期,則清楚
  3. 內(nèi)存淘汰策略,當(dāng)redis內(nèi)存不足以容納更多的key時(shí),則會(huì)觸發(fā)內(nèi)存淘汰策略,可以在配置文件配置。常用有l(wèi)ru(最久沒(méi)訪(fǎng)問(wèn)),lfu(訪(fǎng)問(wèn)頻率最低) random(隨機(jī)),同時(shí)可以配置針對(duì)所有的key,還是設(shè)置了過(guò)期時(shí)間的key執(zhí)行淘汰。

5、看你們公司使用的是MySQL,你們使用的是哪種存儲(chǔ)引擎,為什么?MyISAM和InnoDB的區(qū)別

小伙伴說(shuō),他是參考《尼恩Java面試寶典》中Mysql 面試專(zhuān)題中的Mysql原理、MyISAM和InnoDB的對(duì)比去吹的

6、mysql索引的底層數(shù)據(jù)結(jié)構(gòu)是什么,為什么選擇這種數(shù)據(jù)結(jié)構(gòu)

小伙伴從以下6個(gè)維度去 “吹?!?#xff0c; 吹到 面試官 “口水直流,不能自已”

  • 首先,索引的底層數(shù)據(jù)結(jié)構(gòu)
  • 其次,時(shí)間復(fù)雜度對(duì)比
  • 再次:為什么索引采用B+樹(shù),而不采用Hash這種結(jié)構(gòu)
  • 再次:為什么不用二叉樹(shù)
  • 再次:為什么不用紅黑二叉樹(shù)
  • 最后:為什么沒(méi)有采用B樹(shù),或則說(shuō)B-樹(shù)?

索引的底層數(shù)據(jù)結(jié)構(gòu)有

  1. 樹(shù)Tree,準(zhǔn)確的說(shuō)是B+樹(shù)
  2. Hash

時(shí)間復(fù)雜度對(duì)比

Hash的時(shí)間O(1)

Tree的O(logn)

為什么索引采用B+樹(shù),而不采用Hash這種結(jié)構(gòu)?

Hash這種結(jié)構(gòu)對(duì)與獲取單條記錄時(shí)的查詢(xún)效率是要比B+樹(shù)效率要高的,但是對(duì)與數(shù)據(jù)的范圍查找效率就很低,特別是對(duì)于數(shù)據(jù)量大的時(shí)候(10萬(wàn) 甚至百萬(wàn)級(jí)別的數(shù)據(jù))。

為什么低?它是根據(jù)字段值算出獲取一個(gè)hash值,然后根據(jù)hash值找到在索引表中查找出hash值對(duì)應(yīng)的數(shù)據(jù)行,它的索引沒(méi)有按順序存儲(chǔ)

B+樹(shù):是一種多路平衡樹(shù),一個(gè)橫向存放多個(gè)節(jié)點(diǎn),并且它的非葉子節(jié)點(diǎn)都只存放指向子節(jié)點(diǎn)的索引指針,不存放數(shù)據(jù)。所有非葉子節(jié)點(diǎn)都存放一個(gè)節(jié)點(diǎn)在葉子節(jié)點(diǎn)上,并且這個(gè)葉子節(jié)點(diǎn)是一個(gè)有序的列表結(jié)構(gòu)。

當(dāng)我們查一個(gè)范圍數(shù)據(jù)時(shí),通過(guò)B+樹(shù)搜索

多路:一課樹(shù)每個(gè)節(jié)點(diǎn)最多可以擁有大于2個(gè)子節(jié)點(diǎn)的樹(shù)

平衡樹(shù): 一顆樹(shù)左子樹(shù)和右子樹(shù)保持相對(duì)平衡,不會(huì)出現(xiàn)一邊層級(jí)特別多,一邊層級(jí)特別少的情況

為什么不用二叉樹(shù)?

二叉樹(shù)為非平衡樹(shù),如果是有序遞變的數(shù)據(jù),很有可能就會(huì)變成左邊樹(shù)層級(jí)過(guò)高,或則右邊樹(shù)的層級(jí)過(guò)高,甚至是退化成鏈表。

層級(jí)過(guò)高為什么就不能用了呢?

假設(shè)是1,2,3,4,5,6這樣的數(shù)據(jù),如果我們要找到底部6這個(gè)數(shù)據(jù),就要進(jìn)行6次IO(加載磁盤(pán)數(shù)據(jù)進(jìn)內(nèi)存,索引是在磁盤(pán)文件中以表的形式存在的)才能找到。如果按一次IO10ms計(jì)算,60ms也不算什么。但是假設(shè)是100萬(wàn)呢?1001000010ms,也就是10000s,換算成分鐘也就是167,所以這種結(jié)構(gòu)肯定是不行的。

為什么不用紅黑二叉樹(shù)?

紅黑二叉樹(shù)一種平衡樹(shù),雖然它不會(huì)出現(xiàn)有一樹(shù)的層級(jí)過(guò)高的情況,但是它還是沒(méi)有從根本上解決樹(shù)的層級(jí)問(wèn)題,隨著數(shù)據(jù)量增大,樹(shù)的層級(jí)會(huì)越來(lái)越高。要遍歷葉子節(jié)點(diǎn)的數(shù)據(jù)IO消耗還是過(guò)高。

為什么沒(méi)有采用B樹(shù),或則說(shuō)B-樹(shù)?

B樹(shù)雖然雖然通過(guò)多路平衡樹(shù)解決了樹(shù)的高度問(wèn)題,但是它對(duì)與訪(fǎng)問(wèn)數(shù)據(jù)的查找效率還是低下的,對(duì)于數(shù)據(jù)訪(fǎng)問(wèn)在非葉子節(jié)點(diǎn)和葉子節(jié)點(diǎn)都有的范圍,它不僅非葉子節(jié)點(diǎn)的遍歷還需要做葉子節(jié)點(diǎn)的遍歷。

總體來(lái)說(shuō):選擇B+樹(shù)是因?yàn)樗哂幸韵聝?yōu)點(diǎn):

  1. 查詢(xún)效率高:B+樹(shù)的搜索性能非常接近二叉樹(shù),而且它的查詢(xún)效率更高,因?yàn)樗拿總€(gè)節(jié)點(diǎn)都包含很多關(guān)鍵字,可以支持范圍查詢(xún)。
  2. 空間利用率高:B+樹(shù)的每個(gè)節(jié)點(diǎn)都包含很多關(guān)鍵字,所以它的空間利用率更高,可以支持更多的索引。
  3. 適用于外部存儲(chǔ):B+樹(shù)的節(jié)點(diǎn)之間的距離比較大,所以它更適用于外部存儲(chǔ),可以減少內(nèi)存開(kāi)銷(xiāo)。

因此,B+樹(shù)是一種非常適合用于MySQL索引的底層數(shù)據(jù)結(jié)構(gòu),它可以提供高效、穩(wěn)定、可靠的查詢(xún)性能。

7、說(shuō)說(shuō)什么情況下索引失效

小伙伴說(shuō),他是參考《尼恩Java面試寶典》中Mysql 面試專(zhuān)題中的索引失效面試題去吹的, 面試官非常滿(mǎn)意

8、手寫(xiě)代碼:設(shè)計(jì)一個(gè)分布式自增id生成服務(wù)

設(shè)計(jì)一個(gè)分布式自增id生成服務(wù)的步驟如下:

  1. 選擇合適的分布式ID生成算法,例如Snowflake、Apache Skywalking等。
  2. 設(shè)計(jì)分布式ID生成服務(wù)的架構(gòu),包括節(jié)點(diǎn)的部署、負(fù)載均衡、數(shù)據(jù)同步等。
  3. 實(shí)現(xiàn)分布式ID生成服務(wù)的代碼,包括生成ID的算法、節(jié)點(diǎn)的連接和數(shù)據(jù)同步等。
  4. 部署分布式ID生成服務(wù),并進(jìn)行測(cè)試和性能優(yōu)化。

下面是一個(gè)簡(jiǎn)單的Java實(shí)現(xiàn):

public class DistributedIdGenerator {private static final int PARTITION_ID = 1; // 分區(qū)IDprivate static final int NODE_ID = 1; // 節(jié)點(diǎn)IDprivate static final int SEQUENCE = 1; // 序列號(hào)private static final long SEQUENCE_ROOT = 1L << 32; // 序列號(hào)根節(jié)點(diǎn)private static final long MAX_ID = SEQUENCE_ROOT + 1 - 1L << 32; // 最大IDprivate static final long TIMESTAMP = System.currentTimeMillis() / 1000; // 時(shí)間戳private static final long MACHINE_ID = UUID.randomUUID().getMostSignificantBits(); // 機(jī)器IDprivate static final int SCALE = 10; // 位數(shù)private static final int SHIFT = 22; // 位移private static final int PARTITION_SIZE = 1 << SCALE; // 分區(qū)大小private static final DistributedIdGenerator instance = new DistributedIdGenerator();private static int sequence = 0; // 當(dāng)前節(jié)點(diǎn)的序列號(hào)private static long lastId = SEQUENCE_ROOT; // 上一次生成的IDprivate static Map<Integer, Long> partitionMap = new HashMap<>(); // 分區(qū)ID和最大ID的映射private DistributedIdGenerator() {// 初始化分區(qū)ID和節(jié)點(diǎn)IDpartitionMap.put(PARTITION_ID, SEQUENCE_ROOT);partitionMap.put(NODE_ID, SEQUENCE_ROOT);}public static synchronized long generateId() {// 獲取當(dāng)前節(jié)點(diǎn)的序列號(hào)sequence = (sequence + 1) & SEQUENCE_ROOT;if (sequence == 0) {// 如果序列號(hào)溢出,則從上一次生成的ID開(kāi)始sequence = partitionMap.get(PARTITION_ID);if (sequence == SEQUENCE_ROOT) {// 如果分區(qū)ID溢出,則從最大ID開(kāi)始sequence = partitionMap.get(NODE_ID);if (sequence == SEQUENCE_ROOT) {// 如果節(jié)點(diǎn)ID溢出,則從最大ID開(kāi)始sequence = SEQUENCE_ROOT;}}}// 獲取當(dāng)前時(shí)間的毫秒數(shù)long now = System.currentTimeMillis() / 1000;// 計(jì)算IDlong id = ((now - TIMESTAMP) << SHIFT) | (MACHINE_ID << SCALE) | (sequence << SEQUENCE_SHIFT) | lastId;// 如果ID溢出,則從最大ID開(kāi)始if (id > MAX_ID) {id = SEQUENCE_ROOT;}// 更新上一次生成的IDlastId = id;// 更新分區(qū)ID和節(jié)點(diǎn)ID的映射partitionMap.put(PARTITION_ID, partitionMap.get(PARTITION_ID) + PARTITION_SIZE);partitionMap.put(NODE_ID, partitionMap.get(NODE_ID) + PARTITION_SIZE);// 返回IDreturn id;}
}

這個(gè)實(shí)現(xiàn)使用了Snowflake算法,通過(guò)獲取當(dāng)前時(shí)間的毫秒數(shù)、機(jī)器ID和序列號(hào)來(lái)生成ID。在生成ID時(shí),首先獲取當(dāng)前節(jié)點(diǎn)的序列號(hào),如果序列號(hào)溢出,則從上一次生成的ID開(kāi)始。如果分區(qū)ID和節(jié)點(diǎn)ID都溢出,則從最大ID開(kāi)始。最后,計(jì)算出ID并更新上一次生成的ID和分區(qū)ID和節(jié)點(diǎn)ID的映射。

9、有沒(méi)有了解過(guò)網(wǎng)絡(luò)安全問(wèn)題,常見(jiàn)的網(wǎng)絡(luò)攻擊有哪些,原理是什么,可以怎么解決

小伙伴從以下4個(gè)維度去 “吹?!?#xff0c; 吹到 面試官 “口水直流,不能自已”

  • 首先,XSS 跨站腳本攻擊
  • 其次,CSRF 跨站請(qǐng)求偽造
  • 再次:DDoS 分布式拒絕服務(wù)攻擊
  • 再次:SQL 注入

一、XSS 跨站腳本攻擊

XSS 攻擊是指攻擊者通過(guò)在受信任的網(wǎng)頁(yè)上注入惡意腳本,使得腳本在用戶(hù)瀏覽器中執(zhí)行,從而竊取用戶(hù)敏感信息、劫持會(huì)話(huà)或執(zhí)行其他惡意行為。XSS 攻擊的原理是利用網(wǎng)頁(yè)中的漏洞,將攻擊者的惡意腳本注入到網(wǎng)頁(yè)中,然后當(dāng)用戶(hù)瀏覽該網(wǎng)頁(yè)時(shí),瀏覽器會(huì)執(zhí)行該惡意腳本。

解決 XSS 攻擊的方法包括:

  • 輸入驗(yàn)證:對(duì)用戶(hù)輸入的數(shù)據(jù)進(jìn)行有效性驗(yàn)證,過(guò)濾掉無(wú)效或惡意的輸入。
  • 輸出過(guò)濾:在輸出用戶(hù)輸入數(shù)據(jù)到網(wǎng)頁(yè)上之前,對(duì)數(shù)據(jù)進(jìn)行過(guò)濾,去掉其中的惡意腳本代碼。
  • 安全編碼:使用安全的編碼方式,避免在網(wǎng)頁(yè)中嵌入惡意腳本。
  • 瀏覽器安全設(shè)置:設(shè)置瀏覽器的安全選項(xiàng),禁用或限制腳本執(zhí)行,阻止 XSS 攻擊。

二、CSRF 跨站請(qǐng)求偽造

CSRF 攻擊是指攻擊者通過(guò)偽造用戶(hù)的請(qǐng)求,向網(wǎng)站服務(wù)器發(fā)送惡意請(qǐng)求,從而操縱用戶(hù)賬戶(hù)或執(zhí)行其他惡意行為。CSRF 攻擊的原理是利用網(wǎng)站應(yīng)用程序中的漏洞,繞過(guò)網(wǎng)站的安全驗(yàn)證機(jī)制,以用戶(hù)的身份執(zhí)行惡意請(qǐng)求。

解決 CSRF 攻擊的方法包括:

  • 添加 token:在請(qǐng)求中添加一個(gè)隨機(jī)生成的 token,服務(wù)器驗(yàn)證該 token 是否合法,以判斷請(qǐng)求是否來(lái)自合法用戶(hù)。
  • 采用 POST 方法:使用 POST 方法提交表單,因?yàn)?POST 方法不能被緩存,從而避免 CSRF 攻擊。
  • 限制 HTTP 方法:對(duì)網(wǎng)站應(yīng)用程序進(jìn)行安全配置,限制允許使用的 HTTP 方法,禁止使用 GET、POST 等可被偽造的方法。

三、DDoS 分布式拒絕服務(wù)攻擊

DDoS 攻擊是指攻擊者通過(guò)控制大量僵尸主機(jī),向目標(biāo)主機(jī)發(fā)送海量流量,從而癱瘓目標(biāo)主機(jī)或使其服務(wù)不可用。DDoS 攻擊的原理是通過(guò)大量流量消耗目標(biāo)主機(jī)的帶寬和資源,使其無(wú)法正常提供服務(wù)。

解決 DDoS 攻擊的方法包括:

  • 流量清洗:使用流量清洗設(shè)備對(duì)入侵流量進(jìn)行過(guò)濾和清洗,阻斷攻擊流量。
  • 負(fù)載均衡:使用負(fù)載均衡設(shè)備,將攻擊流量分發(fā)到多個(gè)服務(wù)器上,減輕目標(biāo)服務(wù)器的壓力。
  • 擴(kuò)大帶寬:增加網(wǎng)絡(luò)帶寬,提高網(wǎng)絡(luò)容量,使攻擊流量無(wú)法占據(jù)主導(dǎo)地位。
  • 關(guān)閉不必要服務(wù):關(guān)閉不必要的服務(wù),減少攻擊目標(biāo),從而降低攻擊效果。

四、SQL 注入

SQL 注入攻擊是指攻擊者通過(guò)在 Web 應(yīng)用程序的輸入框中注入惡意 SQL 語(yǔ)句,從而獲取未授權(quán)的訪(fǎng)問(wèn)權(quán)限或竊取敏感數(shù)據(jù)。SQL 注入攻擊的原理是利用應(yīng)用程序中的漏洞,將惡意 SQL 語(yǔ)句插入到 SQL 查詢(xún)語(yǔ)句中,從而操縱數(shù)據(jù)庫(kù)。

  1. 輸入驗(yàn)證:對(duì)用戶(hù)輸入的數(shù)據(jù)進(jìn)行有效性驗(yàn)證,過(guò)濾掉無(wú)效或惡意的輸入??梢允褂谜齽t表達(dá)式、字符串匹配等方法對(duì)輸入數(shù)據(jù)進(jìn)行過(guò)濾,確保輸入數(shù)據(jù)的合法性和準(zhǔn)確性。
  2. 參數(shù)化查詢(xún):使用參數(shù)化查詢(xún),避免將用戶(hù)輸入的數(shù)據(jù)直接拼接到 SQL 查詢(xún)語(yǔ)句中。參數(shù)化查詢(xún)可以將用戶(hù)輸入的數(shù)據(jù)與 SQL 語(yǔ)句分離,從而避免 SQL 注入漏洞。在 Java 中,可以使用 PreparedStatement 語(yǔ)句進(jìn)行參數(shù)化查詢(xún)。
  3. 預(yù)編譯語(yǔ)句:使用預(yù)編譯語(yǔ)句進(jìn)行預(yù)處理,可以將 SQL 語(yǔ)句和參數(shù)分離,從而避免 SQL 注入漏洞。預(yù)編譯語(yǔ)句可以在第一次執(zhí)行時(shí)編譯成機(jī)器碼,后續(xù)執(zhí)行時(shí)直接使用機(jī)器碼執(zhí)行,提高了執(zhí)行效率。在 Java 中,可以使用 PreparedStatement 語(yǔ)句進(jìn)行預(yù)編譯。
  4. Mybatis 映射語(yǔ)句:在 Mybatis 映射語(yǔ)句中,使用#{xxx}而不是${}來(lái)表示參數(shù)。這樣可以避免將用戶(hù)輸入的數(shù)據(jù)直接拼接到 SQL 查詢(xún)語(yǔ)句中,從而避免 SQL 注入漏洞。在 Mybatis 中,可以使用#{param1}, #{param2}等語(yǔ)法來(lái)表示參數(shù)。
  5. 訪(fǎng)問(wèn)控制:對(duì)數(shù)據(jù)庫(kù)的訪(fǎng)問(wèn)進(jìn)行嚴(yán)格的權(quán)限控制,禁止未經(jīng)授權(quán)的用戶(hù)訪(fǎng)問(wèn)敏感數(shù)據(jù)??梢允褂脭?shù)據(jù)庫(kù)的訪(fǎng)問(wèn)控制機(jī)制,如 ACL、RLS 等,對(duì)數(shù)據(jù)庫(kù)的訪(fǎng)問(wèn)進(jìn)行限制。此外,可以在應(yīng)用程序中對(duì)用戶(hù)進(jìn)行身份驗(yàn)證和授權(quán),確保只有授權(quán)用戶(hù)可以訪(fǎng)問(wèn)敏感數(shù)據(jù)。
  6. 數(shù)據(jù)加密:對(duì)敏感數(shù)據(jù)進(jìn)行加密,防止數(shù)據(jù)泄露,即使被攻擊者竊取也無(wú)法獲取明文數(shù)據(jù)??梢允褂眉用芩惴?#xff0c;如 AES、SSL 等,對(duì)敏感數(shù)據(jù)進(jìn)行加密。在 Java 中,可以使用 Java 加密算法或第三方加密庫(kù)進(jìn)行加密。

10、平時(shí)在開(kāi)發(fā)接口或者設(shè)計(jì)項(xiàng)目的時(shí)候如何保證安全性的

小伙伴從以下8個(gè)維度去 “吹?!?#xff0c; 吹到 面試官 “口水直流,不能自已”

  1. 簽名和加密:確保數(shù)據(jù)在傳輸過(guò)程中不被篡改或竊取,可以使用簽名和加密技術(shù)。簽名可以確保數(shù)據(jù)的完整性和真實(shí)性,而加密可以確保數(shù)據(jù)的保密性。常用的簽名算法有 SHA-256、SHA-3 等,加密算法有 AES、RSA 等。
  2. IP 檢測(cè)和限流:通過(guò)檢測(cè)請(qǐng)求的 IP 地址,可以實(shí)現(xiàn)訪(fǎng)問(wèn)控制和限流。例如,可以限制某個(gè) IP 地址的請(qǐng)求次數(shù)或限制某個(gè) IP 地址的訪(fǎng)問(wèn)權(quán)限。這可以幫助防止 DDoS 攻擊和其他惡意行為。
  3. 接口冪等性:確保接口在多次調(diào)用下不會(huì)產(chǎn)生副作用,可以實(shí)現(xiàn)接口的冪等性。例如,在處理支付接口時(shí),可以確保同一個(gè)訂單多次支付不會(huì)產(chǎn)生重復(fù)扣款。
  4. 特殊字符過(guò)濾:通過(guò)過(guò)濾特殊字符,可以防止 XSS 和 SQL 注入攻擊。例如,可以過(guò)濾掉單引號(hào)、雙引號(hào)、斜杠等特殊字符,避免攻擊者通過(guò)注入惡意代碼來(lái)執(zhí)行攻擊。
  5. 防止 CSRF 攻擊:CSRF 攻擊是一種利用用戶(hù)瀏覽器發(fā)起惡意請(qǐng)求的攻擊方式。為了防止 CSRF 攻擊,可以使用 token 技術(shù),即在客戶(hù)端生成一個(gè)隨機(jī)的 token,在請(qǐng)求時(shí)將其發(fā)送給服務(wù)器,服務(wù)器驗(yàn)證 token 的合法性,從而確保請(qǐng)求是合法的。
  6. 防止XSS攻擊:可以使用過(guò)濾器來(lái)過(guò)濾掉一些可能會(huì)導(dǎo)致XSS攻擊的特殊字符或代碼,例如反斜杠、單引號(hào)等。
  7. SQL注入的攻擊:可以使用預(yù)編譯語(yǔ)句或者參數(shù)化查詢(xún)來(lái)防止SQL注入的攻擊,從而保護(hù)數(shù)據(jù)庫(kù)的數(shù)據(jù)安全。
  8. 輸入驗(yàn)證:在接收用戶(hù)輸入時(shí),需要對(duì)輸入進(jìn)行驗(yàn)證,確保輸入的格式和內(nèi)容是合法的。例如,可以驗(yàn)證輸入的數(shù)字范圍、字符長(zhǎng)度等,避免因?yàn)檩斎氩缓戏ǘ鴮?dǎo)致的安全漏洞。

11、使用Redis集群時(shí)可能會(huì)存在什么問(wèn)題

小伙伴從以下7個(gè)維度去 “吹?!?#xff0c; 吹到 面試官 “口水直流,不能自已”

  • 首先,數(shù)據(jù)一致性問(wèn)題
  • 其次,性能問(wèn)題
  • 再次:可用性問(wèn)題
  • 再次:負(fù)載均衡問(wèn)題
  • 再次:網(wǎng)絡(luò)延遲問(wèn)題
  • 再次:節(jié)點(diǎn)故障問(wèn)題
  • 最后,安全問(wèn)題

一、數(shù)據(jù)一致性問(wèn)題

在 Redis 集群中,當(dāng)多個(gè)節(jié)點(diǎn)同時(shí)進(jìn)行寫(xiě)操作時(shí),可能會(huì)導(dǎo)致數(shù)據(jù)不一致。例如,當(dāng)節(jié)點(diǎn) A 和節(jié)點(diǎn) B 同時(shí)嘗試向同一個(gè) key 寫(xiě)入數(shù)據(jù)時(shí),如果節(jié)點(diǎn) A 先寫(xiě)入成功,而節(jié)點(diǎn) B 的后寫(xiě)入操作失敗,則導(dǎo)致該 key 的數(shù)據(jù)在節(jié)點(diǎn) A 和節(jié)點(diǎn) B 上不一致。為了解決這個(gè)問(wèn)題,可以使用 Redis 集群的主節(jié)點(diǎn)來(lái)協(xié)調(diào)多個(gè)節(jié)點(diǎn)之間的數(shù)據(jù)寫(xiě)入操作,確保數(shù)據(jù)的一致性。

解決方法

  • 使用主節(jié)點(diǎn)進(jìn)行寫(xiě)操作協(xié)調(diào):所有寫(xiě)操作必須經(jīng)過(guò)主節(jié)點(diǎn)協(xié)調(diào),由主節(jié)點(diǎn)分配節(jié)點(diǎn)進(jìn)行寫(xiě)操作,并確保所有節(jié)點(diǎn)寫(xiě)操作的順序和一致性。這樣可以保證數(shù)據(jù)的一致性,但會(huì)增加主節(jié)點(diǎn)的負(fù)擔(dān),降低性能。
  • 使用分布式鎖:在寫(xiě)操作之前,節(jié)點(diǎn)需要獲取分布式鎖,以確保在該節(jié)點(diǎn)完成寫(xiě)操作之前,其他節(jié)點(diǎn)無(wú)法進(jìn)行寫(xiě)操作。這樣可以避免多個(gè)節(jié)點(diǎn)同時(shí)進(jìn)行寫(xiě)操作導(dǎo)致的數(shù)據(jù)不一致問(wèn)題。然而,分布式鎖可能會(huì)帶來(lái)性能瓶頸,因?yàn)殒i的競(jìng)爭(zhēng)可能會(huì)導(dǎo)致節(jié)點(diǎn)之間的延遲。

二、性能問(wèn)題

在使用 Redis 集群時(shí),可能會(huì)出現(xiàn)性能瓶頸。例如,當(dāng)集群中的某個(gè)節(jié)點(diǎn)出現(xiàn)網(wǎng)絡(luò)延遲或負(fù)載過(guò)高時(shí),可能會(huì)導(dǎo)致整個(gè)集群的性能下降。此外,由于 Redis 集群需要進(jìn)行數(shù)據(jù)同步和協(xié)調(diào),因此可能會(huì)增加額外的延遲和開(kāi)銷(xiāo),從而影響集群的性能。

解決方法

  • 增加節(jié)點(diǎn)數(shù)量:通過(guò)增加節(jié)點(diǎn)數(shù)量來(lái)提高集群的性能和吞吐量。更多的節(jié)點(diǎn)意味著更多的計(jì)算和存儲(chǔ)資源,可以更好地支持并發(fā)訪(fǎng)問(wèn)和數(shù)據(jù)處理。
  • 優(yōu)化網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu):通過(guò)優(yōu)化網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu),例如使用高速網(wǎng)絡(luò)、增加網(wǎng)絡(luò)帶寬、使用負(fù)載均衡器等,來(lái)提高集群的性能和吞吐量。
  • 優(yōu)化 Redis 配置:通過(guò)調(diào)整 Redis 的配置參數(shù),例如調(diào)整緩存大小、調(diào)整持久化策略、優(yōu)化數(shù)據(jù)庫(kù)文件等,來(lái)提高集群的性能和吞吐量。

三、可用性問(wèn)題

在使用 Redis 集群時(shí),如果某個(gè)節(jié)點(diǎn)出現(xiàn)故障或宕機(jī),可能會(huì)導(dǎo)致整個(gè)集群的不可用。

解決方法

需要使用 Redis 集群的高可用性機(jī)制來(lái)確保集群的可用性,例如使用多個(gè)節(jié)點(diǎn)進(jìn)行數(shù)據(jù)冗余和備份,以便在節(jié)點(diǎn)故障或宕機(jī)時(shí)能夠自動(dòng)切換到備用節(jié)點(diǎn)。

可以通過(guò)以下兩種方式來(lái)實(shí)現(xiàn):

  • 數(shù)據(jù)冗余備份:在 Redis 集群中,可以將數(shù)據(jù)備份到多個(gè)節(jié)點(diǎn)上,以確保在節(jié)點(diǎn)故障或宕機(jī)時(shí),仍有其他節(jié)點(diǎn)可以提供數(shù)據(jù)服務(wù)。
  • 故障轉(zhuǎn)移:在 Redis 集群中,可以使用故障轉(zhuǎn)移機(jī)制,將故障節(jié)點(diǎn)的服務(wù)切換到其他節(jié)點(diǎn)上,以確保集群的可用性。故障轉(zhuǎn)移可以通過(guò)主節(jié)點(diǎn)檢測(cè)節(jié)點(diǎn)狀態(tài),或者通過(guò)心跳機(jī)制實(shí)現(xiàn)。

四、負(fù)載均衡問(wèn)題

在Redis集群中,每個(gè)節(jié)點(diǎn)都需要承擔(dān)一定的負(fù)載,如果負(fù)載不均衡,可能會(huì)導(dǎo)致某些節(jié)點(diǎn)的負(fù)載過(guò)高,影響系統(tǒng)的性能。

解決方法

可以使用Redis Cluster來(lái)解決負(fù)載均衡問(wèn)題。Redis Cluster會(huì)根據(jù)節(jié)點(diǎn)的負(fù)載情況,自動(dòng)地將負(fù)載較高的節(jié)點(diǎn)上的數(shù)據(jù)轉(zhuǎn)移到負(fù)載較低的節(jié)點(diǎn)上,從而實(shí)現(xiàn)負(fù)載均衡。

五、網(wǎng)絡(luò)延遲問(wèn)題

在Redis集群中,節(jié)點(diǎn)之間的通信需要通過(guò)網(wǎng)絡(luò)進(jìn)行,如果網(wǎng)絡(luò)延遲過(guò)高,可能會(huì)導(dǎo)致數(shù)據(jù)的延遲,影響系統(tǒng)的性能。

解決方法

可以使用Redis Cluster來(lái)解決網(wǎng)絡(luò)延遲問(wèn)題。Redis Cluster會(huì)根據(jù)節(jié)點(diǎn)之間的網(wǎng)絡(luò)延遲情況,自動(dòng)地將數(shù)據(jù)轉(zhuǎn)移到網(wǎng)絡(luò)延遲較低的節(jié)點(diǎn)上,從而降低數(shù)據(jù)的延遲。

六、節(jié)點(diǎn)故障問(wèn)題

在Redis集群中,如果某個(gè)節(jié)點(diǎn)發(fā)生故障,可能會(huì)導(dǎo)致數(shù)據(jù)的不一致性或者系統(tǒng)的不可用性。

解決方法

可以使用Redis Cluster來(lái)解決節(jié)點(diǎn)故障問(wèn)題。Redis Cluster會(huì)自動(dòng)地將故障節(jié)點(diǎn)上的數(shù)據(jù)轉(zhuǎn)移到其他節(jié)點(diǎn)上,保證數(shù)據(jù)的一致性和系統(tǒng)的可用性。

七、安全問(wèn)題

在Redis集群中,數(shù)據(jù)的安全性也是一個(gè)問(wèn)題,如果節(jié)點(diǎn)的安全性受到攻擊,可能會(huì)導(dǎo)致數(shù)據(jù)的泄露或者被篡改。因此,在使用Redis集群時(shí),需要注意數(shù)據(jù)的安全性,并采取相應(yīng)的安全措施。

解決方法

可以使用Redis Cluster來(lái)解決安全問(wèn)題。Redis Cluster會(huì)對(duì)節(jié)點(diǎn)的安全性進(jìn)行監(jiān)控,并采取相應(yīng)的安全措施,例如限制節(jié)點(diǎn)的訪(fǎng)問(wèn)權(quán)限、加密數(shù)據(jù)等,從而保證數(shù)據(jù)的安全性。

12、有沒(méi)有了解過(guò)cap和base原則

小伙伴從以下8個(gè)維度去 “吹?!?#xff0c; 吹到 面試官 “口水直流,不能自已”

  • 首先,CAP理論
  • 其次,CAP理論的 一致性(C:Consistency)
  • 再次:CAP理論的 可用性(A:Availability)
  • 再次:CAP理論的 分區(qū)容錯(cuò)性(P:Partition tolerance)
  • 再次:BASE 理論
  • 再次:BASE 理論的 Basically Available
  • 再次:BASE 理論的 Soft State
  • 最后,BASE 理論的 Eventually Consistent

一、CAP理論

CAP理論作為分布式系統(tǒng)的基礎(chǔ)理論,指的是在一個(gè)分布式系統(tǒng)中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分區(qū)容錯(cuò)性),這三個(gè)要素最多只能同時(shí)實(shí)現(xiàn)兩點(diǎn)。

一致性(C:Consistency):

一致性是指數(shù)據(jù)在多個(gè)副本之間能否保持一致的特性。例如一個(gè)數(shù)據(jù)在某個(gè)分區(qū)節(jié)點(diǎn)更新之后,在其他分區(qū)節(jié)點(diǎn)讀出來(lái)的數(shù)據(jù)也是更新之后的數(shù)據(jù)。

可用性(A:Availability):

可用性是指系統(tǒng)提供的服務(wù)必須一直處于可用的狀態(tài),對(duì)于用戶(hù)的每一個(gè)操作請(qǐng)求總是能夠在有限的時(shí)間內(nèi)返回結(jié)果。這里的重點(diǎn)是"有限時(shí)間內(nèi)"和"返回結(jié)果"。

分區(qū)容錯(cuò)性(P:Partition tolerance):

分布式系統(tǒng)在遇到任何網(wǎng)絡(luò)分區(qū)故障的時(shí)候,仍然需要能夠保證對(duì)外提供滿(mǎn)足一致性和可用性的服務(wù)。

選擇說(shuō)明
CA放棄分區(qū)容錯(cuò)性,加強(qiáng)一致性和可用性,其實(shí)就是傳統(tǒng)的單機(jī)數(shù)據(jù)庫(kù)的選擇
AP放棄一致性,分區(qū)容錯(cuò)性和可用性,這是很多分布式系統(tǒng)設(shè)計(jì)時(shí)的選擇
CP放棄可用性,追求一致性和分區(qū)容錯(cuò)性,網(wǎng)絡(luò)問(wèn)題會(huì)直接讓整個(gè)系統(tǒng)不可用

二、BASE 理論

BASE 理論, 是對(duì)CAP中AP的一個(gè)擴(kuò)展,對(duì)于我們的業(yè)務(wù)系統(tǒng),我們考慮犧牲一致性來(lái)?yè)Q取系統(tǒng)的可用性和分區(qū)容錯(cuò)性。BASE是Basically Available(基本可用),Soft state(軟狀態(tài)),和 Eventually consistent(最終一致性)三個(gè)短語(yǔ)的縮寫(xiě)。

Basically Available

基本可用:通過(guò)支持局部故障而不是系統(tǒng)全局故障來(lái)實(shí)現(xiàn)的。如將用戶(hù)分區(qū)在 5 個(gè)數(shù)據(jù)庫(kù)服務(wù)器上,一個(gè)用戶(hù)數(shù)據(jù)庫(kù)的故障只影響這臺(tái)特定主機(jī)那 20% 的用戶(hù),其他用戶(hù)不受影響。

Soft State

軟狀態(tài),狀態(tài)可以有一段時(shí)間不同步

Eventually Consistent

最終一致,最終數(shù)據(jù)是一致的就可以了,而不是時(shí)時(shí)保持強(qiáng)一致。

13、zk是如何保證一致性的

小伙伴從以下4個(gè)維度去 “吹?!?#xff0c; 吹到 面試官 “口水直流,不能自已”

  • 首先,ZAB協(xié)議(Zookeeper原子消息廣播協(xié)議)
  • 其次,選主
  • 再次:選主后的數(shù)據(jù)同步
  • 再次:事務(wù)操作

一:ZAB協(xié)議(Zookeeper原子消息廣播協(xié)議)

zookeeper實(shí)現(xiàn)數(shù)據(jù)一致性的核心是ZAB協(xié)議(Zookeeper原子消息廣播協(xié)議)。該協(xié)議需要做到以下幾點(diǎn):

(1)集群在半數(shù)以下節(jié)點(diǎn)宕機(jī)的情況下,能正常對(duì)外提供服務(wù);

(2)客戶(hù)端的寫(xiě)請(qǐng)求全部轉(zhuǎn)交給leader來(lái)處理,leader需確保寫(xiě)變更能實(shí)時(shí)同步給所有follower及observer;

(3)leader宕機(jī)或整個(gè)集群重啟時(shí),需要確保那些已經(jīng)在leader服務(wù)器上提交的事務(wù)最終被所有服務(wù)器都提交,確保丟棄那些只在leader服務(wù)器上被提出的事務(wù),并保證集群能快速恢復(fù)到故障前的狀態(tài)。

Zab協(xié)議有兩種模式, 崩潰恢復(fù)(選主+數(shù)據(jù)同步)和消息廣播(事務(wù)操作)。

任何時(shí)候都需要保證只有一個(gè)主進(jìn)程負(fù)責(zé)進(jìn)行事務(wù)操作,而如果主進(jìn)程崩潰了,就需要迅速選舉出一個(gè)新的主進(jìn)程。主進(jìn)程的選舉機(jī)制與事務(wù)操作機(jī)制是緊密相關(guān)的。

下面詳細(xì)講解這三個(gè)場(chǎng)景的協(xié)議規(guī)則,從細(xì)節(jié)去探索ZAB協(xié)議的數(shù)據(jù)一致性原理。

二、選主

leader選舉是zk中最重要的技術(shù)之一,也是保證分布式數(shù)據(jù)一致性的關(guān)鍵所在。當(dāng)集群中的一臺(tái)服務(wù)器處于如下兩種情況之一時(shí),就會(huì)進(jìn)入leader選舉階段——服務(wù)器初始化啟動(dòng)、服務(wù)器運(yùn)行期間無(wú)法與leader保持連接。

選舉階段,集群間互傳的消息稱(chēng)為投票,投票Vote主要包括二個(gè)維度的信息:ID、ZXID

  • ID 被推舉的leader的服務(wù)器ID,集群中的每個(gè)zk節(jié)點(diǎn)啟動(dòng)前就要配置好這個(gè)全局唯一的ID。
  • ZXID 被推舉的leader的事務(wù)ID ,該值是從機(jī)器DataTree內(nèi)存中取的,即事務(wù)已經(jīng)在機(jī)器上被commit過(guò)了。

節(jié)點(diǎn)進(jìn)入選舉階段后的大體執(zhí)行邏輯如下:

(1)設(shè)置狀態(tài)為L(zhǎng)OOKING,初始化內(nèi)部投票Vote (id,zxid) 數(shù)據(jù)至內(nèi)存,并將其廣播到集群其它節(jié)點(diǎn)。節(jié)點(diǎn)首次投票都是選舉自己作為leader,將自身的服務(wù)ID、處理的最近一個(gè)事務(wù)請(qǐng)求的ZXID(ZXID是從內(nèi)存數(shù)據(jù)庫(kù)里取的,即該節(jié)點(diǎn)最近一個(gè)完成commit的事務(wù)id)及當(dāng)前狀態(tài)廣播出去。然后進(jìn)入循環(huán)等待及處理其它節(jié)點(diǎn)的投票信息的流程中。

(2)循環(huán)等待流程中,節(jié)點(diǎn)每收到一個(gè)外部的Vote信息,都需要將其與自己內(nèi)存Vote數(shù)據(jù)進(jìn)行PK,規(guī)則為取ZXID大的,若ZXID相等,則取ID大的那個(gè)投票。若外部投票勝選,節(jié)點(diǎn)需要將該選票覆蓋之前的內(nèi)存Vote數(shù)據(jù),并再次廣播出去;同時(shí)還要統(tǒng)計(jì)是否有過(guò)半的贊同者與新的內(nèi)存投票數(shù)據(jù)一致,無(wú)則繼續(xù)循環(huán)等待新的投票,有則需要判斷l(xiāng)eader是否在贊同者之中,在則退出循環(huán),選舉結(jié)束,根據(jù)選舉結(jié)果及各自角色切換狀態(tài),leader切換成LEADING、follower切換到FOLLOWING、observer切換到OBSERVING狀態(tài)。

算法細(xì)節(jié)可參照FastLeaderElection.lookForLeader(),主要有三個(gè)線(xiàn)程在工作:選舉線(xiàn)程(主動(dòng)調(diào)用lookForLeader方法的線(xiàn)程,通過(guò)阻塞隊(duì)列sendqueue及recvqueue與其它兩個(gè)線(xiàn)程協(xié)作)、WorkerReceiver線(xiàn)程(選票接收器,不斷獲取其它服務(wù)器發(fā)來(lái)的選舉消息,篩選后會(huì)保存到recvqueue隊(duì)列中。zk服務(wù)器啟動(dòng)時(shí),開(kāi)始正常工作,不停止)以及WorkerSender線(xiàn)程(選票發(fā)送器,會(huì)不斷地從sendqueue隊(duì)列中獲取待發(fā)送的選票,并廣播至集群)。WorkerReceiver線(xiàn)程一直在工作,即使當(dāng)前節(jié)點(diǎn)處于LEADING或者FOLLOWING狀態(tài),它起到了一個(gè)過(guò)濾的作用,當(dāng)前節(jié)點(diǎn)為L(zhǎng)OOKING時(shí),才會(huì)將外部投票信息轉(zhuǎn)交給選舉線(xiàn)程處理;如果當(dāng)前節(jié)點(diǎn)處于非LOOKING狀態(tài),收到了處于LOOKING狀態(tài)的節(jié)點(diǎn)投票數(shù)據(jù)(外部節(jié)點(diǎn)重啟或網(wǎng)絡(luò)抖動(dòng)情況下),說(shuō)明發(fā)起投票的節(jié)點(diǎn)數(shù)據(jù)跟集群不一致,這時(shí),當(dāng)前節(jié)點(diǎn)需要向集群廣播出最新的內(nèi)存Vote(id,zxid),落后節(jié)點(diǎn)收到該Vote后,會(huì)及時(shí)注冊(cè)到leader上,并完成數(shù)據(jù)同步,跟上集群節(jié)奏,提供正常服務(wù)。

三、選主后的數(shù)據(jù)同步

選主算法中的zxid是從內(nèi)存數(shù)據(jù)庫(kù)中取的最新事務(wù)id,事務(wù)操作是分兩階段的(提出階段和提交階段),leader生成提議并廣播給followers,收到半數(shù)以上的ACK后,再?gòu)V播commit消息,同時(shí)將事務(wù)操作應(yīng)用到內(nèi)存中。

follower收到提議后先將事務(wù)寫(xiě)到本地事務(wù)日志,然后反饋ACK,等接到leader的commit消息時(shí),才會(huì)將事務(wù)操作應(yīng)用到內(nèi)存中??梢?jiàn),選主只是選出了內(nèi)存數(shù)據(jù)是最新的節(jié)點(diǎn),僅僅靠這個(gè)是無(wú)法保證已經(jīng)在leader服務(wù)器上提交的事務(wù)最終被所有服務(wù)器都提交。比如leader發(fā)起提議P1,并收到半數(shù)以上follower關(guān)于P1的ACK后,在廣播commit消息之前宕機(jī)了,選舉產(chǎn)生的新leader之前是follower,未收到關(guān)于P1的commit消息,內(nèi)存中是沒(méi)有P1的數(shù)據(jù)。而ZAB協(xié)議的設(shè)計(jì)是需要保證選主后,P1是需要應(yīng)用到集群中的。這塊的邏輯是通過(guò)選主后的數(shù)據(jù)同步來(lái)彌補(bǔ)。

選主后,節(jié)點(diǎn)需要切換狀態(tài),leader切換成LEADING狀態(tài)后的流程如下:

(1)重新加載本地磁盤(pán)上的數(shù)據(jù)快照至內(nèi)存,并從日志文件中取出快照之后的所有事務(wù)操作,逐條應(yīng)用至內(nèi)存,并添加到已提交事務(wù)緩存commitedProposals。這樣能保證日志文件中的事務(wù)操作,必定會(huì)應(yīng)用到leader的內(nèi)存數(shù)據(jù)庫(kù)中。

(2)獲取learner發(fā)送的FOLLOWERINFO/OBSERVERINFO信息,并與自身commitedProposals比對(duì),確定采用哪種同步方式,不同的learner可能采用不同同步方式(DIFF同步、TRUNC+DIFF同步、SNAP同步)。這里是拿learner內(nèi)存中的zxid與leader內(nèi)存中的commitedProposals(min、max)比對(duì),如果zxid介于min與max之間,但又不存在于commitedProposals中時(shí),說(shuō)明該zxid對(duì)應(yīng)的事務(wù)需要TRUNC回滾;如果 zxid 介于min與max之間且存在于commitedProposals中,則leader需要將zxid+1~max 間所有事務(wù)同步給learner,這些內(nèi)存缺失數(shù)據(jù),很可能是因?yàn)閘eader切換過(guò)程中造成commit消息丟失,learner只完成了事務(wù)日志寫(xiě)入,未完成提交事務(wù),未應(yīng)用到內(nèi)存。

(3)leader主動(dòng)向所有l(wèi)earner發(fā)送同步數(shù)據(jù)消息,每個(gè)learner有自己的發(fā)送隊(duì)列,互不干擾。同步結(jié)束時(shí),leader會(huì)向learner發(fā)送NEWLEADER指令,同時(shí)learner會(huì)反饋一個(gè)ACK。當(dāng)leader接收到來(lái)自learner的ACK消息后,就認(rèn)為當(dāng)前l(fā)earner已經(jīng)完成了數(shù)據(jù)同步,同時(shí)進(jìn)入“過(guò)半策略”等待階段。當(dāng)leader統(tǒng)計(jì)到收到了一半已上的ACK時(shí),會(huì)向所有已經(jīng)完成數(shù)據(jù)同步的learner發(fā)送一個(gè)UPTODATE指令,用來(lái)通知learner集群已經(jīng)完成了數(shù)據(jù)同步,可以對(duì)外服務(wù)了。

細(xì)節(jié)可參照Leader.lead() 、Follower.followLeader()及LearnerHandler類(lèi)。

四、事務(wù)操作

ZAB協(xié)議對(duì)于事務(wù)操作的處理是一個(gè)類(lèi)似于二階段提交過(guò)程。

針對(duì)客戶(hù)端的事務(wù)請(qǐng)求,leader服務(wù)器會(huì)為其生成對(duì)應(yīng)的事務(wù)proposal,并將其發(fā)送給集群中所有follower機(jī)器,然后收集各自的選票,最后進(jìn)行事務(wù)提交。

流程如下圖

ZAB協(xié)議的二階段提交過(guò)程中,移除了中斷邏輯(事務(wù)回滾),所有follower服務(wù)器要么正常反饋leader提出的事務(wù)proposal,要么就拋棄leader服務(wù)器。follower收到proposal后的處理很簡(jiǎn)單,將該proposal寫(xiě)入到事務(wù)日志,然后立馬反饋ACK給leader,也就是說(shuō)如果不是網(wǎng)絡(luò)、內(nèi)存或磁盤(pán)等問(wèn)題,follower肯定會(huì)寫(xiě)入成功,并正常反饋ACK。leader收到過(guò)半follower的ACK后,會(huì)廣播commit消息給所有follower,并將事務(wù)應(yīng)用到內(nèi)存;follower收到commit消息后會(huì)將事務(wù)應(yīng)用到內(nèi)存。

ZAB協(xié)議中多次用到“過(guò)半”設(shè)計(jì)策略 ,該策略是zk在A(yíng)(可用性)與C(一致性)間做的取舍,也是zk具有高容錯(cuò)特性的本質(zhì)。相較分布式事務(wù)中的2PC(二階段提交協(xié)議)的“全量通過(guò)”,ZAB協(xié)議可用性更高(犧牲了部分一致性),能在集群半數(shù)以下服務(wù)宕機(jī)時(shí)正常對(duì)外提供服務(wù)。

14、你如何設(shè)計(jì)一個(gè)能抗住大流量的系統(tǒng),說(shuō)說(shuō)設(shè)計(jì)方案

小伙伴說(shuō),他是參考《尼恩Java面試寶典》中架構(gòu)設(shè)計(jì)面試專(zhuān)題 吹的, 面試官非常滿(mǎn)意

15、有沒(méi)有了解過(guò)緩存策略有哪些

小伙伴從以下3個(gè)維度去 “吹?!?#xff0c; 吹到 面試官 “口水直流,不能自已”

  • 首先,Cache Aside(旁路緩存)策略
  • 其次,Read/Write Through(讀穿 / 寫(xiě)穿)策略
  • 再次:Write Back(寫(xiě)回)策略

一、Cache Aside(旁路緩存)策略

我們可以在更新數(shù)據(jù)時(shí)不更新緩存,而是刪除緩存中的數(shù)據(jù),在讀取數(shù)據(jù)時(shí),發(fā)現(xiàn)緩存中沒(méi)了數(shù)據(jù)之后,再?gòu)臄?shù)據(jù)庫(kù)中讀取數(shù)據(jù),更新到緩存中。

緩存讀寫(xiě)過(guò)程

緩存讀寫(xiě)過(guò)程

這個(gè)策略就是我們使用緩存最常見(jiàn)的策略,Cache Aside 策略(也叫旁路緩存策略),這個(gè)策略數(shù)據(jù)以數(shù)據(jù)庫(kù)中的數(shù)據(jù)為準(zhǔn),緩存中的數(shù)據(jù)是按需加載的。它可以分為讀策略和寫(xiě)策略,

讀策略的步驟是:

從緩存中讀取數(shù)據(jù);

如果緩存命中,則直接返回?cái)?shù)據(jù);

如果緩存不命中,則從數(shù)據(jù)庫(kù)中查詢(xún)數(shù)據(jù);

查詢(xún)到數(shù)據(jù)后,將數(shù)據(jù)寫(xiě)入到緩存中,并且返回給用戶(hù)。

寫(xiě)策略的步驟是:

更新數(shù)據(jù)庫(kù)中的記錄;

刪除緩存記錄。

注意

Cache Aside 存在的最大的問(wèn)題是當(dāng)寫(xiě)入比較頻繁時(shí),緩存中的數(shù)據(jù)會(huì)被頻繁地清理,這樣會(huì)對(duì)緩存的命中率有一些影響。如果你的業(yè)務(wù)對(duì)緩存命中率有嚴(yán)格的要求,那么可以考慮兩種解決方案:

  1. 一種做法是在更新數(shù)據(jù)時(shí)也更新緩存,只是在更新緩存前先加一個(gè)分布式鎖,因?yàn)檫@樣在同一時(shí)間只允許一個(gè)線(xiàn)程更新緩存,就不會(huì)產(chǎn)生并發(fā)問(wèn)題了。當(dāng)然這么做對(duì)于寫(xiě)入的性能會(huì)有一些影響;
  2. 另一種做法同樣也是在更新數(shù)據(jù)時(shí)更新緩存,只是給緩存加一個(gè)較短的過(guò)期時(shí)間,這樣即使出現(xiàn)緩存不一致的情況,緩存的數(shù)據(jù)也會(huì)很快過(guò)期,對(duì)業(yè)務(wù)的影響也是可以接受。

二、Read/Write Through(讀穿 / 寫(xiě)穿)策略

這個(gè)策略的核心原則是用戶(hù)只與緩存打交道,由緩存和數(shù)據(jù)庫(kù)通信,寫(xiě)入或者讀取數(shù)據(jù)。這就好比你在匯報(bào)工作的時(shí)候只對(duì)你的直接上級(jí)匯報(bào),再由你的直接上級(jí)匯報(bào)給他的上級(jí),你是不能越級(jí)匯報(bào)的。

Write Through 的策略是這樣的:先查詢(xún)要寫(xiě)入的數(shù)據(jù)在緩存中是否已經(jīng)存在,如果已經(jīng)存在,則更新緩存中的數(shù)據(jù),并且由緩存組件同步更新到數(shù)據(jù)庫(kù)中,如果緩存中數(shù)據(jù)不存在,我們把這種情況叫做“Write Miss(寫(xiě)失效)”。

一般來(lái)說(shuō),我們可以選擇兩種“Write Miss”方式:一個(gè)是“Write Allocate(按寫(xiě)分配)”,做法是寫(xiě)入緩存相應(yīng)位置,再由緩存組件同步更新到數(shù)據(jù)庫(kù)中;另一個(gè)是“No-write allocate(不按寫(xiě)分配)”,做法是不寫(xiě)入緩存中,而是直接更新到數(shù)據(jù)庫(kù)中。

在 Write Through 策略中,我們一般選擇“No-write allocate”方式,原因是無(wú)論采用哪種“Write Miss”方式,我們都需要同步將數(shù)據(jù)更新到數(shù)據(jù)庫(kù)中,而“No-write allocate”方式相比“Write Allocate”還減少了一次緩存的寫(xiě)入,能夠提升寫(xiě)入的性能。

Read Through 策略就簡(jiǎn)單一些,它的步驟是這樣的:先查詢(xún)緩存中數(shù)據(jù)是否存在,如果存在則直接返回,如果不存在,則由緩存組件負(fù)責(zé)從數(shù)據(jù)庫(kù)中同步加載數(shù)據(jù)。

下面是 Read Through/Write Through 策略的示意圖:

Read/Write Through策略示意圖

Read/Write Through策略示意圖

Read Through/Write Through 策略的特點(diǎn)是由緩存節(jié)點(diǎn)而非用戶(hù)來(lái)和數(shù)據(jù)庫(kù)打交道,在我們開(kāi)發(fā)過(guò)程中相比 Cache Aside 策略要少見(jiàn)一些,原因是我們經(jīng)常使用的分布式緩存組件,無(wú)論是 Memcached 還是 Redis 都不提供寫(xiě)入數(shù)據(jù)庫(kù),或者自動(dòng)加載數(shù)據(jù)庫(kù)中的數(shù)據(jù)的功能。而我們?cè)谑褂帽镜鼐彺娴臅r(shí)候可以考慮使用這種策略,比如說(shuō)在上一節(jié)中提到的本地緩存 Guava Cache 中的 Loading Cache 就有 Read Through 策略的影子。

我們看到 Write Through 策略中寫(xiě)數(shù)據(jù)庫(kù)是同步的,這對(duì)于性能來(lái)說(shuō)會(huì)有比較大的影響,因?yàn)橄啾扔趯?xiě)緩存,同步寫(xiě)數(shù)據(jù)庫(kù)的延遲就要高很多了。那么我們可否異步地更新數(shù)據(jù)庫(kù)?這就是我們接下來(lái)要提到的“Write Back”策略。

三、Write Back(寫(xiě)回)策略

這個(gè)策略的核心思想是在寫(xiě)入數(shù)據(jù)時(shí)只寫(xiě)入緩存,并且把緩存塊兒標(biāo)記為“臟”的。而臟塊兒只有被再次使用時(shí)才會(huì)將其中的數(shù)據(jù)寫(xiě)入到后端存儲(chǔ)中。

需要注意的是,在“Write Miss”的情況下,我們采用的是“Write Allocate”的方式,也就是在寫(xiě)入后端存儲(chǔ)的同時(shí)要寫(xiě)入緩存,這樣我們?cè)谥蟮膶?xiě)請(qǐng)求中都只需要更新緩存即可,而無(wú)需更新后端存儲(chǔ)了,我將 Write back 策略的示意圖放在了下面:

Write Back 寫(xiě)策略示意圖

Write Back 寫(xiě)回策略示意圖

如果使用 Write Back 策略的話(huà),讀的策略也有一些變化了。

我們?cè)谧x取緩存時(shí)如果發(fā)現(xiàn)緩存命中則直接返回緩存數(shù)據(jù)。如果緩存不命中則尋找一個(gè)可用的緩存塊兒,如果這個(gè)緩存塊兒是“臟”的,就把緩存塊兒中之前的數(shù)據(jù)寫(xiě)入到后端存儲(chǔ)中,并且從后端存儲(chǔ)加載數(shù)據(jù)到緩存塊兒,如果不是臟的,則由緩存組件將后端存儲(chǔ)中的數(shù)據(jù)加載到緩存中,最后我們將緩存設(shè)置為不是臟的,返回?cái)?shù)據(jù)就好了。

Write Back 讀策略示意圖

Write Back 讀策略示意圖

其實(shí)這種策略不能被應(yīng)用到我們常用的數(shù)據(jù)庫(kù)和緩存的場(chǎng)景中,它是計(jì)算機(jī)體系結(jié)構(gòu)中的設(shè)計(jì),比如我們?cè)谙虼疟P(pán)中寫(xiě)數(shù)據(jù)時(shí)采用的就是這種策略。無(wú)論是操作系統(tǒng)層面的 Page Cache,還是日志的異步刷盤(pán),亦或是消息隊(duì)列中消息的異步寫(xiě)入磁盤(pán),大多采用了這種策略。因?yàn)檫@個(gè)策略在性能上的優(yōu)勢(shì)毋庸置疑,它避免了直接寫(xiě)磁盤(pán)造成的隨機(jī)寫(xiě)問(wèn)題,畢竟寫(xiě)內(nèi)存和寫(xiě)磁盤(pán)的隨機(jī) I/O 的延遲相差了幾個(gè)數(shù)量級(jí)呢。

但因?yàn)榫彺嬉话闶褂脙?nèi)存,而內(nèi)存是非持久化的,所以一旦緩存機(jī)器掉電,就會(huì)造成原本緩存中的臟塊兒數(shù)據(jù)丟失。所以你會(huì)發(fā)現(xiàn)系統(tǒng)在掉電之后,之前寫(xiě)入的文件會(huì)有部分丟失,就是因?yàn)?Page Cache 還沒(méi)有來(lái)得及刷盤(pán)造成的。

當(dāng)然,你依然可以在一些場(chǎng)景下使用這個(gè)策略,在使用時(shí),我想給你的落地建議是:你在向低速設(shè)備寫(xiě)入數(shù)據(jù)的時(shí)候,可以在內(nèi)存里先暫存一段時(shí)間的數(shù)據(jù),甚至做一些統(tǒng)計(jì)匯總,然后定時(shí)地刷新到低速設(shè)備上。比如說(shuō),你在統(tǒng)計(jì)你的接口響應(yīng)時(shí)間的時(shí)候,需要將每次請(qǐng)求的響應(yīng)時(shí)間打印到日志中,然后監(jiān)控系統(tǒng)收集日志后再做統(tǒng)計(jì)。但是如果每次請(qǐng)求都打印日志無(wú)疑會(huì)增加磁盤(pán) I/O,那么不如把一段時(shí)間的響應(yīng)時(shí)間暫存起來(lái),經(jīng)過(guò)簡(jiǎn)單的統(tǒng)計(jì)平均耗時(shí),每個(gè)耗時(shí)區(qū)間的請(qǐng)求數(shù)量等等,然后定時(shí)地,批量地打印到日志中。

總結(jié)

  1. Cache Aside 是我們?cè)谑褂梅植际骄彺鏁r(shí)最常用的策略,你可以在實(shí)際工作中直接拿來(lái)使用。推薦使用
  2. Read/Write Through 和 Write Back 策略需要緩存組件的支持,所以比較適合你在實(shí)現(xiàn)本地緩存組件的時(shí)候使用;
  3. Write Back 策略是計(jì)算機(jī)體系結(jié)構(gòu)中的策略,不過(guò)寫(xiě)入策略中的只寫(xiě)緩存,異步寫(xiě)入后端存儲(chǔ)的策略倒是有很多的應(yīng)用場(chǎng)景。

參考文獻(xiàn)

尼恩的系統(tǒng)架構(gòu)知識(shí)圖譜(一張價(jià)值10w的系統(tǒng)架構(gòu)知識(shí)圖譜)

www.processon.com/view/link/60fb9421637689719d246739

尼恩的秒殺系統(tǒng)的架構(gòu)

www.processon.com/view/link/61148c2b1e08536191d8f92f

尼恩說(shuō)在最后

在尼恩的(50+)讀者社區(qū)中,很多、很多小伙伴需要進(jìn)大廠(chǎng)、拿高薪。

尼恩團(tuán)隊(duì),會(huì)持續(xù)結(jié)合一些大廠(chǎng)的面試真題,給大家梳理一下學(xué)習(xí)路徑,看看大家需要學(xué)點(diǎn)啥?

前面用多篇文章,給大家介紹阿里、百度、字節(jié)、滴滴的真題:

《太猛了,靠“吹?!边^(guò)順豐一面,月薪30K》

《炸裂了…京東一面索命40問(wèn),過(guò)了就50W+》

《問(wèn)麻了…阿里一面索命27問(wèn),過(guò)了就60W+》

《百度狂問(wèn)3小時(shí),大廠(chǎng)offer到手,小伙真狠!》

《餓了么太狠:面?zhèn)€高級(jí)Java,抖這多硬活、狠活》

《字節(jié)狂問(wèn)一小時(shí),小伙offer到手,太狠了!》

《收個(gè)滴滴Offer:從小伙三面經(jīng)歷,看看需要學(xué)點(diǎn)啥?》

這些真題,都會(huì)收入到 史上最全、持續(xù)升級(jí)的 PDF電子書(shū) 《尼恩Java面試寶典》。

本文收錄于 《尼恩Java面試寶典》 V95版。

基本上,把尼恩的 《尼恩Java面試寶典》吃透,大廠(chǎng)offer很容易拿到滴。

另外,下一期的 大廠(chǎng)面經(jīng),更加精彩,具體可以參見(jiàn)文末公號(hào)。

《尼恩 架構(gòu)筆記》《尼恩高并發(fā)三部曲》《尼恩Java面試寶典》PDF,請(qǐng)到下面公號(hào)【技術(shù)自由圈】取↓↓↓

http://www.risenshineclean.com/news/7155.html

相關(guān)文章:

  • 廣西桂林為什么窮優(yōu)化網(wǎng)站排名技巧
  • 龍華做棋牌網(wǎng)站建設(shè)多少錢(qián)網(wǎng)絡(luò)口碑營(yíng)銷(xiāo)名詞解釋
  • 自己做的網(wǎng)站顯示不出來(lái)國(guó)際最新新聞熱點(diǎn)事件
  • WordPress碎語(yǔ)山東服務(wù)好的seo
  • 一個(gè)完整的動(dòng)態(tài)網(wǎng)站開(kāi)發(fā)東莞seo整站優(yōu)化火速
  • dede5.7 做的網(wǎng)站 下 加一個(gè)discuz論壇網(wǎng)站統(tǒng)計(jì)分析工具
  • 德陽(yáng)網(wǎng)站開(kāi)發(fā)熊掌號(hào)互聯(lián)網(wǎng)推廣是干什么的
  • 上傳網(wǎng)站到google什么是百度權(quán)重
  • 代碼網(wǎng)站開(kāi)發(fā)seo搜索引擎優(yōu)化是什么意思
  • 建設(shè)企業(yè)網(wǎng)站可行性分析百度一下進(jìn)入首頁(yè)
  • wordpress門(mén)戶(hù)網(wǎng)站模板下載互聯(lián)網(wǎng)營(yíng)銷(xiāo)做什么
  • 做自動(dòng)采集電影網(wǎng)站有什么處罰上海網(wǎng)絡(luò)推廣培訓(xùn)機(jī)構(gòu)
  • 專(zhuān)業(yè)做網(wǎng)站優(yōu)化個(gè)人網(wǎng)站模板
  • 茶網(wǎng)站開(kāi)發(fā)的意義目的建站之星官方網(wǎng)站
  • 菏澤網(wǎng)站建設(shè)效果網(wǎng)址大全2345
  • 影響網(wǎng)站建設(shè)價(jià)格的因素有比較經(jīng)典的營(yíng)銷(xiāo)案例
  • 購(gòu)物網(wǎng)站 購(gòu)物車(chē)界面如何做html做一個(gè)簡(jiǎn)單的網(wǎng)頁(yè)
  • 1920的做網(wǎng)站做多大重慶seo推廣運(yùn)營(yíng)
  • 網(wǎng)站服務(wù)器數(shù)據(jù)庫(kù)百度推廣找誰(shuí)做靠譜
  • wordpress仿今日主題網(wǎng)站優(yōu)化包括哪些
  • 怎么進(jìn)入wordpress后臺(tái)紹興網(wǎng)站快速排名優(yōu)化
  • cmseasy做網(wǎng)站簡(jiǎn)單嗎營(yíng)銷(xiāo)策劃培訓(xùn)
  • 商丘市網(wǎng)站建設(shè)推廣福建企業(yè)seo推廣
  • 青島網(wǎng)站建設(shè)和優(yōu)化網(wǎng)絡(luò)營(yíng)銷(xiāo)師有前途嗎
  • 網(wǎng)站建設(shè) 石家莊網(wǎng)站建設(shè)哪家公司好
  • 廣告公司做網(wǎng)站寧波seo網(wǎng)絡(luò)推廣代理公司
  • 嘉興 網(wǎng)站制作網(wǎng)站seo分析案例
  • 東莞南城網(wǎng)站開(kāi)發(fā)公司關(guān)鍵詞的優(yōu)化和推廣
  • 哪個(gè)網(wǎng)站做任務(wù)賺錢(qián)多org域名注冊(cè)
  • 怎樣做國(guó)外網(wǎng)站推廣東莞網(wǎng)站建設(shè)推廣公司