<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>

          螞蟻金服一面:十道經(jīng)典面試題解析

          共 11144字,需瀏覽 23分鐘

           ·

          2021-09-02 17:27

          1. 用到分布式事務(wù)嘛?為什么用這種方案,有其他方案嘛?

          什么是分布式事務(wù)

          談到事務(wù),我們就會想到數(shù)據(jù)庫事務(wù),很容易就想到原子性、一致性、持久性、隔離性。
          分布式事務(wù)跟數(shù)據(jù)庫事務(wù)有點不一樣,它是指事務(wù)的參與者、支持事務(wù)的服務(wù)器、資源服務(wù)器以及事務(wù)管理器分別位于不同的分布式系統(tǒng)的不同節(jié)點之上。簡單來說,分布式事務(wù)指的就是分布式系統(tǒng)中的事務(wù),它的存在就是為了保證不同數(shù)據(jù)庫節(jié)點的數(shù)據(jù)一致性。

          分布式事務(wù)基礎(chǔ)

          分布式事務(wù)需要需要知道CAP理論BASE理論。

          CAP理論

          • 一致性(C:Consistency):一致性是指數(shù)據(jù)在多個副本之間能否保持一致的特性。例如一個數(shù)據(jù)在某個分區(qū)節(jié)點更新之后,在其他分區(qū)節(jié)點讀出來的數(shù)據(jù)也是更新之后的數(shù)據(jù)。
          • 可用性(A:Availability):可用性是指系統(tǒng)提供的服務(wù)必須一直處于可用的狀態(tài),對于用戶的每一個操作請求總是能夠在有限的時間內(nèi)返回結(jié)果。這里的重點是"有限時間內(nèi)"和"返回結(jié)果"。
          • 分區(qū)容錯性(P:Partition tolerance):分布式系統(tǒng)在遇到任何網(wǎng)絡(luò)分區(qū)故障的時候,仍然需要能夠保證對外提供滿足一致性和可用性的服務(wù)。
          一個分布式系統(tǒng)中,CAP理論它只能同時滿足(一致性、可用性、分區(qū)容錯性)中的兩點。

          BASE 理論

          BASE 理論, 是對CAP中AP的一個擴展,對于我們的業(yè)務(wù)系統(tǒng),我們考慮犧牲一致性來換取系統(tǒng)的可用性和分區(qū)容錯性。BASE是Basically Available(基本可用),Soft state(軟狀態(tài)),和 Eventually consistent(最終一致性)三個短語的縮寫。
          • 基本可用是指,通過支持局部故障而不是系統(tǒng)全局故障來實現(xiàn)的;
          • Soft State表示狀態(tài)可以有一段時間不同步;
          • 最終一致,最終數(shù)據(jù)是一致的就可以了,而不是實時保持強一致。

          分布式事務(wù)的幾種解決方案

          • 2PC(二階段提交)方案,事務(wù)的提交分為兩個階段:準備階段和提交執(zhí)行方案。
          • TCC(即Try、Confirm、Cancel),它采用了補償機制,核心思想是:針對每個操作,都要注冊一個與其對應(yīng)的確認和補償(撤銷)操作。
          • 本地消息表,它的核心思想就是將分布式事務(wù)拆分成本地事務(wù)進行處理。
          • 最大努力通知,實現(xiàn)最大努力通知,可以采用MQ的ack機制。
          • Saga事務(wù),它的核心思想是將長事務(wù)拆分為多個本地短事務(wù),由Saga事務(wù)協(xié)調(diào)器協(xié)調(diào),如果正常結(jié)束那就正常完成,如果某個步驟失敗,則根據(jù)相反順序一次調(diào)用補償操作。
          業(yè)界目前使用本地消息表這種方案是比較多的,它的核心思想就是將分布式事務(wù)拆分成本地事務(wù)進行處理??梢钥匆幌禄镜膶崿F(xiàn)流程圖吧:
          對于消息發(fā)送方:
          • 首先需要有一個消息表,記錄著消息狀態(tài)相關(guān)信息。
          • 業(yè)務(wù)數(shù)據(jù)和消息表在同一個數(shù)據(jù)庫,即要保證它倆在同一個本地事務(wù)。
          • 在本地事務(wù)中處理完業(yè)務(wù)數(shù)據(jù)和寫消息表操作后,通過寫消息到MQ消息隊列。
          • 消息會發(fā)到消息消費方,如果發(fā)送失敗,即進行重試。
          消息消費方:
          • 處理消息隊列中的消息,完成自己的業(yè)務(wù)邏輯。
          • 此時如果本地事務(wù)處理成功,則表明已經(jīng)處理成功了。
          • 如果本地事務(wù)處理失敗,那么就會重試執(zhí)行。
          • 如果是業(yè)務(wù)上面的失敗,給消息生產(chǎn)方發(fā)送一個業(yè)務(wù)補償消息,通知進行回滾等操作。
          生產(chǎn)方和消費方定時掃描本地消息表,把還沒處理完成的消息或者失敗的消息再發(fā)送一遍。如果有靠譜的自動對賬補賬邏輯,這種方案還是非常實用的。

          2.JDK6、7、8分別提供了哪些新特性

          JDK 6 新特性
          • Desktop類(它允許一個Java應(yīng)用程序啟動本地的另一個應(yīng)用程序去處理URI或文件請求)
          • 使用JAXB2來實現(xiàn)對象與XML之間的映射
          • 輕量級 Http Server API
          • 插入式注解處理API(lombok框架基于這個特性實現(xiàn))
          • STAX(是JDK6中一種處理XML文檔的API)
          JDK 7的新特性
          • switch 支持String字符串類型
          • try-with-resources,資源自動關(guān)閉
          • 整數(shù)類型如(byte,short,int,long)能夠用二進制來表示
          • 數(shù)字常量支持下劃線
          • 泛型實例化類型自動推斷,即”<>”
          • 一個catch中捕獲多個異常類型,用(|)分隔開
          • 增強的文件系統(tǒng)
          • Fork/join 框架
          JDK8 的新特性
          • lambada表達式
          • 函數(shù)式接口
          • 方法引用
          • 默認方法
          • Stream API
          • Optional
          • Date Time API(如LocalDate)
          • 重復(fù)注解
          • Base64
          • JVM的新特性(如元空間Metaspace代替持久代)

          3. https原理,工作流程

          • HTTPS = HTTP + SSL/TLS,即用SSL/TLS對數(shù)據(jù)進行加密和解密,Http進行傳輸。
          • SSL,即Secure Sockets Layer(安全套接層協(xié)議),是網(wǎng)絡(luò)通信提供安全及數(shù)據(jù)完整性的一種安全協(xié)議。
          • TLS,即Transport Layer Security(安全傳輸層協(xié)議),它是SSL3.0的后續(xù)版本。
          1. 客戶端發(fā)起Https請求,連接到服務(wù)器的443端口。
          2. 服務(wù)器必須要有一套數(shù)字證書(證書內(nèi)容有公鑰、證書頒發(fā)機構(gòu)、失效日期等)。
          3. 服務(wù)器將自己的數(shù)字證書發(fā)送給客戶端(公鑰在證書里面,私鑰由服務(wù)器持有)。
          4. 客戶端收到數(shù)字證書之后,會驗證證書的合法性。如果證書驗證通過,就會生成一個隨機的對稱密鑰,用證書的公鑰加密。
          5. 客戶端將公鑰加密后的密鑰發(fā)送到服務(wù)器。
          6. 服務(wù)器接收到客戶端發(fā)來的密文密鑰之后,用自己之前保留的私鑰對其進行非對稱解密,解密之后就得到客戶端的密鑰,然后用客戶端密鑰對返回數(shù)據(jù)進行對稱加密,醬紫傳輸?shù)臄?shù)據(jù)都是密文啦。
          7. 服務(wù)器將加密后的密文返回到客戶端。
          8. 客戶端收到后,用自己的密鑰對其進行對稱解密,得到服務(wù)器返回的數(shù)據(jù)。

          4. 講講java jmm volatile的實現(xiàn)原理

          volatile關(guān)鍵字是Java虛擬機提供的的最輕量級的同步機制,它作為一個修飾符,用來修飾變量。它保證變量對所有線程可見性,禁止指令重排,但是不保證原子性。
          volatile是如何保證可見性的呢?我們先來看下java內(nèi)存模型(jmm)
          • Java虛擬機規(guī)范試圖定義一種Java內(nèi)存模型,來屏蔽掉各種硬件和操作系統(tǒng)的內(nèi)存訪問差異,以實現(xiàn)讓Java程序在各種平臺上都能達到一致的內(nèi)存訪問效果。
          • 為了更好的執(zhí)行性能,java內(nèi)存模型并沒有限制執(zhí)行引擎使用處理器的特定寄存器或緩存來和主內(nèi)存打交道,也沒有限制編譯器進行調(diào)整代碼順序優(yōu)化。所以Java內(nèi)存模型會存在緩存一致性問題和指令重排序問題的。
          • Java內(nèi)存模型規(guī)定所有的變量都是存在主內(nèi)存當(dāng)中,每個線程都有自己的工作內(nèi)存。這里的變量包括實例變量和靜態(tài)變量,但是不包括局部變量,因為局部變量是線程私有的。
          • 線程的工作內(nèi)存保存了被該線程使用的變量的主內(nèi)存副本,線程對變量的所有操作都必須在工作內(nèi)存中進行,而不能直接操作操作主內(nèi)存。并且每個線程不能訪問其他線程的工作內(nèi)存。

          volatile變量,保證新值能立即同步回主內(nèi)存,以及每次使用前立即從主內(nèi)存刷新,所以我們說volatile保證了多線程操作變量的可見性。
          指令重排是指在程序執(zhí)行過程中,為了提高性能, 編譯器和CPU可能會對指令進行重新排序。volatile是如何禁止指令重排的?在Java語言中,有一個先行發(fā)生原則(happens-before)
          • 程序次序規(guī)則:在一個線程內(nèi),按照控制流順序,書寫在前面的操作先行發(fā)生于書寫在后面的操作。
          • 管程鎖定規(guī)則:一個unLock操作先行發(fā)生于后面對同一個鎖額lock操作
          • volatile變量規(guī)則:對一個變量的寫操作先行發(fā)生于后面對這個變量的讀操作
          • 線程啟動規(guī)則:Thread對象的start()方法先行發(fā)生于此線程的每個一個動作
          • 線程終止規(guī)則:線程中所有的操作都先行發(fā)生于線程的終止檢測,我們可以通過Thread.join()方法結(jié)束、Thread.isAlive()的返回值手段檢測到線程已經(jīng)終止執(zhí)行
          • 線程中斷規(guī)則:對線程interrupt()方法的調(diào)用先行發(fā)生于被中斷線程的代碼檢測到中斷事件的發(fā)生
          • 對象終結(jié)規(guī)則:一個對象的初始化完成先行發(fā)生于他的finalize()方法的開始
          • 傳遞性:如果操作A先行發(fā)生于操作B,而操作B又先行發(fā)生于操作C,則可以得出操作A先行發(fā)生于操作C
          實際上volatile保證可見性和禁止指令重排都跟內(nèi)存屏障有關(guān)。我們來看一段volatile使用的demo代碼
          public class Singleton {  
              private volatile static Singleton instance;  
              private Singleton (){}  
              public static Singleton getInstance() {  
              if (instance == null) {  
                  synchronized (Singleton.class) {  
                  if (instance == null) {  
                      instance = new Singleton();  
                  }  
                  }  
              }  
              return instance;  
              }  
          }  
          編譯后,對比有volatile關(guān)鍵字和沒有volatile關(guān)鍵字時所生成的匯編代碼,發(fā)現(xiàn)有volatile關(guān)鍵字修飾時,會多出一個lock addl $0x0,(%esp),即多出一個lock前綴指令,lock指令相當(dāng)于一個「內(nèi)存屏障」
          lock指令相當(dāng)于一個內(nèi)存屏障,它保證以下這幾點:
          • 1.重排序時不能把后面的指令重排序到內(nèi)存屏障之前的位置
          • 2.將本處理器的緩存寫入內(nèi)存
          • 3.如果是寫入動作,會導(dǎo)致其他處理器中對應(yīng)的緩存無效。
          第2點和第3點就是保證volatile保證可見性的體現(xiàn)嘛,第1點就是禁止指令重排列的體現(xiàn)。內(nèi)存屏障又是什么呢?
          內(nèi)存屏障四大分類:(Load 代表讀取指令,Store代表寫入指令)

          為了實現(xiàn)volatile的內(nèi)存語義,Java內(nèi)存模型采取以下的保守策略
          • 在每個volatile寫操作的前面插入一個StoreStore屏障。
          • 在每個volatile寫操作的后面插入一個StoreLoad屏障。
          • 在每個volatile讀操作的后面插入一個LoadLoad屏障。
          • 在每個volatile讀操作的后面插入一個LoadStore屏障。
          有些小伙伴,可能對這個還是有點疑惑,內(nèi)存屏障這玩意太抽象了。我們照著代碼看下吧:
          內(nèi)存屏障保證前面的指令先執(zhí)行,所以這就保證了禁止了指令重排啦,同時內(nèi)存屏障保證緩存寫入內(nèi)存和其他處理器緩存失效,這也就保證了可見性,哈哈~

          5. 講一講7層網(wǎng)絡(luò)模型,tcp的為什么要三次握手

          計算機網(wǎng)路體系結(jié)構(gòu)有三層:OSI七層模型、TCP/IP四層模型、五層體系結(jié)構(gòu),如圖:
          七層模型,亦稱OSI(Open System Interconnection),國際標準化組織(International Organization for Standardization)制定的一個用于計算機或通信系統(tǒng)間互聯(lián)的標準體系。
          • 應(yīng)用層:網(wǎng)絡(luò)服務(wù)與最終用戶的一個接口,常見的協(xié)議有:HTTP FTP  SMTP SNMP DNS.
          • 表示層:數(shù)據(jù)的表示、安全、壓縮。,確保一個系統(tǒng)的應(yīng)用層所發(fā)送的信息可以被另一個系統(tǒng)的應(yīng)用層讀取。
          • 會話層:建立、管理、終止會話,對應(yīng)主機進程,指本地主機與遠程主機正在進行的會話.
          • 傳輸層:定義傳輸數(shù)據(jù)的協(xié)議端口號,以及流控和差錯校驗,協(xié)議有TCP UDP.
          • 網(wǎng)絡(luò)層:進行邏輯地址尋址,實現(xiàn)不同網(wǎng)絡(luò)之間的路徑選擇,協(xié)議有ICMP IGMP IP等.
          • 數(shù)據(jù)鏈路層:在物理層提供比特流服務(wù)的基礎(chǔ)上,建立相鄰結(jié)點之間的數(shù)據(jù)鏈路。
          • 物理層:建立、維護、斷開物理連接。

          6.說說線程池的工作原理

          面試官如果要我們講下線程池工作原理的話,大家講下以下這個流程圖就可以啦:
          為了形象描述線程池執(zhí)行,加深大家的理解,我打個比喻:
          • 核心線程比作公司正式員工
          • 非核心線程比作外包員工
          • 阻塞隊列比作需求池
          • 提交任務(wù)比作提需求
          • 當(dāng)產(chǎn)品提個需求,正式員工(核心線程)先接需求(執(zhí)行任務(wù))
          • 如果正式員工都有需求在做,即核心線程數(shù)已滿),產(chǎn)品就把需求先放需求池(阻塞隊列)。
          • 如果需求池(阻塞隊列)也滿了,但是這時候產(chǎn)品繼續(xù)提需求,怎么辦呢?那就請外包(非核心線程)來做。
          • 如果所有員工(最大線程數(shù)也滿了)都有需求在做了,那就執(zhí)行拒絕策略。
          • 如果外包員工把需求做完了,它經(jīng)過一段(keepAliveTime)空閑時間,就離開公司了。

          7.你們數(shù)據(jù)庫的高可用是怎么實現(xiàn)的?

          高可用,即High Availability,是分布式系統(tǒng)架構(gòu)設(shè)計中必須考慮的因素之一,它通常是指,通過設(shè)計減少系統(tǒng)不能提供服務(wù)的時間。單機部署談不上高可用,因為單點故障問題。高可用都是多個節(jié)點的,我們在考慮MySQL數(shù)據(jù)庫的高可用的架構(gòu)時,需要考慮這幾個方面:
          • 如果數(shù)據(jù)庫節(jié)點宕機,需要盡快回復(fù),保證業(yè)務(wù)不受宕機影響。
          • 從數(shù)據(jù)庫節(jié)點的數(shù)據(jù),盡可能跟主節(jié)點數(shù)據(jù)實時保持一致,至少保證最終一致性。
          • 數(shù)據(jù)庫節(jié)點切換時,數(shù)據(jù)不能缺失。

          7.1 主從或主主半同步復(fù)制

          用雙節(jié)點數(shù)據(jù)庫,搭建單向或者雙向的半同步復(fù)制。架構(gòu)如下:
          通常會和proxy、keepalived等第三方軟件同時使用,即可以用來監(jiān)控數(shù)據(jù)庫的健康,又可以執(zhí)行一系列管理命令。如果主庫發(fā)生故障,切換到備庫后仍然可以繼續(xù)使用數(shù)據(jù)庫。
          這種方案優(yōu)點是架構(gòu)、部署比較簡單,主機宕機直接切換即可。缺點是完全依賴于半同步復(fù)制,半同步復(fù)制退化為異步復(fù)制,無法保證數(shù)據(jù)一致性;另外,還需要額外考慮haproxy、keepalived的高可用機制。

          7.2 半同步復(fù)制優(yōu)化

          半同步復(fù)制機制是可靠的,可以保證數(shù)據(jù)一致性的。但是如果網(wǎng)絡(luò)發(fā)生波動,半同步復(fù)制發(fā)生超時會切換為異步復(fù)制,異復(fù)制是無法保證數(shù)據(jù)的一致性的。因此,可以在半同復(fù)制的基礎(chǔ)上優(yōu)化一下,盡可能保證半同復(fù)制。如雙通道復(fù)制方案
          • 優(yōu)點:這種方案架構(gòu)、部署也比較簡單,主機宕機也是直接切換即可。比方案1的半同步復(fù)制,更能保證數(shù)據(jù)的一致性。
          • 缺點:需要修改內(nèi)核源碼或者使用mysql通信協(xié)議,沒有從根本上解決數(shù)據(jù)一致性問題。

          7.3 高可用架構(gòu)優(yōu)化

          保證高可用,可以把主從雙節(jié)點數(shù)據(jù)庫擴展為數(shù)據(jù)庫集群。Zookeeper可以作為集群管理,它使用分布式算法保證集群數(shù)據(jù)的一致性,可以較好的避免網(wǎng)絡(luò)分區(qū)現(xiàn)象的產(chǎn)生。
          • 優(yōu)點:保證了整個系統(tǒng)的高可用性,擴展性也較好,可以擴展為大規(guī)模集群。
          • 缺點:數(shù)據(jù)一致性仍然依賴于原生的mysql半同步復(fù)制;引入Zookeeper使系統(tǒng)邏輯更復(fù)雜。

          7.4 共享存儲

          共享存儲實現(xiàn)了數(shù)據(jù)庫服務(wù)器和存儲設(shè)備的解耦,不同數(shù)據(jù)庫之間的數(shù)據(jù)同步不再依賴于MySQL的原生復(fù)制功能,而是通過磁盤數(shù)據(jù)同步的手段,來保證數(shù)據(jù)的一致性。
          DRBD磁盤復(fù)制
          DRBD是一個用軟件實現(xiàn)的、無共享的、服務(wù)器之間鏡像塊設(shè)備內(nèi)容的存儲復(fù)制解決方案。主要用于對服務(wù)器之間的磁盤、分區(qū)、邏輯卷等進行數(shù)據(jù)鏡像,當(dāng)用戶將數(shù)據(jù)寫入本地磁盤時,還會將數(shù)據(jù)發(fā)送到網(wǎng)絡(luò)中另一臺主機的磁盤上,這樣的本地主機(主節(jié)點)與遠程主機(備節(jié)點)的數(shù)據(jù)就可以保證實時同步。常用架構(gòu)如下:
          當(dāng)本地主機出現(xiàn)問題,遠程主機上還保留著一份相同的數(shù)據(jù),即可以繼續(xù)使用,保證了數(shù)據(jù)的安全。
          • 優(yōu)點:部署簡單,價格合適,保證數(shù)據(jù)的強一致性
          • 缺點:對IO性能影響較大,從庫不提供讀操作

          7.5 分布式協(xié)議

          分布式協(xié)議可以很好解決數(shù)據(jù)一致性問題。常見的部署方案就是MySQL cluster,它是官方集群的部署方案,通過使用NDB存儲引擎實時備份冗余數(shù)據(jù),實現(xiàn)數(shù)據(jù)庫的高可用性和數(shù)據(jù)一致性。如下:
          • 優(yōu)點:不依賴于第三方軟件,可以實現(xiàn)數(shù)據(jù)的強一致性;
          • 缺點:配置較復(fù)雜;需要使用NDB儲存引擎;至少三節(jié)點;

          8. 讀寫分離的場景下,怎么保證從數(shù)據(jù)庫讀到最新的數(shù)據(jù)?

          數(shù)據(jù)庫讀寫分離,主要解決高并發(fā)時,提高系統(tǒng)的吞吐量。來看下讀寫分離數(shù)據(jù)庫模型:
          • 寫請求是直接寫主庫,然后同步數(shù)據(jù)到從庫
          • 讀請求一般直接讀從庫,除飛強制讀主庫
          在高并發(fā)場景或者網(wǎng)絡(luò)不佳的場景,如果存在較大的主從同步數(shù)據(jù)延遲,這時候讀請求去讀從庫,就會讀到舊數(shù)據(jù)。這時候最簡單暴力的方法,就是強制讀主庫。實際上可以使用緩存標記法。
          • A發(fā)起寫請求,更新主庫數(shù)據(jù),并在緩存中設(shè)置一個標記,表示數(shù)據(jù)已更新,標記格式為:userId+業(yè)務(wù)Id。
          • 設(shè)置此標記,設(shè)置過期時間(估值為主庫和從庫同步延遲的時間)
          • B發(fā)起讀請求,先判斷此請求,在緩存中有沒有更新標記。
          • 如果存在標記,走主庫;如果沒有,請求走從庫。
          這個方案,解決了數(shù)據(jù)不一致問題,但是每次請求都要先跟緩存打交道,會影響系統(tǒng)吞吐。

          9. 如何保證MySQL數(shù)據(jù)不丟?

          MySQL這種關(guān)系型數(shù)據(jù)庫,是日志先行策略(Write-Ahead Logging),只要binlog和redo log日志能保證持久化到磁盤,我們就能確保MySQL異常重啟后,數(shù)據(jù)不丟失。

          binlog日志

          binlog,又稱為二進制日志,它會記錄數(shù)據(jù)庫執(zhí)行更改的所有操作,但是不包括查詢select等操作。一般用于恢復(fù)、復(fù)制等功能。它的格式有三種:statement、mixed和row。
          • statement:每一條會修改數(shù)據(jù)的sql都會記錄到binlog中,不建議使用。
          • row:基于行的變更情況記錄,會記錄行更改前后的內(nèi)容,推薦使用。
          • mixed:混合statement和row兩個模式,不建議使用。
          binlog 的寫入機制是怎樣的呢?
          事務(wù)執(zhí)行過程中,先把日志寫到 binlog cache,事務(wù)提交的時候,再把binlog cache寫到binlog文件中 。
          系統(tǒng)為每個客戶端線程分配一個binlog cache,其大小值控制參數(shù)是binlog_cache_size。如果binlog cache的值超過閥值,就會臨時持久化到磁盤。當(dāng)事務(wù)提交的時候,再將 binlog cache中完整的事務(wù)持久化到磁盤中,并且清空binlog cache。
          binlog寫文件
          binlog寫文件分write和fsync兩個過程:
          • write:指把日志寫到文件系統(tǒng)的page cache,并沒有把數(shù)據(jù)持久化到磁盤,因此速度較快。
          • fsync,實際的寫盤操作,即把數(shù)據(jù)持久化到磁盤。
          write和fsync的寫入時機,是由變量sync_binlog控制的:
          如果IO出現(xiàn)性能瓶頸,可以將sync_binlog設(shè)置成一個較大的值。比如設(shè)置為(100~1000)。但是,會存在數(shù)據(jù)丟失的風(fēng)險,當(dāng)主機異常重啟時,會丟失N個最近提交的事務(wù)binlog

          redo log日志

          redo log,又稱為重做日志文件,只記錄事務(wù)對數(shù)據(jù)頁做了哪些修改,它記錄的是數(shù)據(jù)修改之后的值。redo 有三種狀態(tài)
          • 物理上是在MySQL進程內(nèi)存中,存在redo log buffer中,
          • 物理上在文件系統(tǒng)的page cache里,寫到磁盤 (write),但是還沒有持久化(fsync)。
          • 存在hard disk,已經(jīng)持久化到磁盤。
          日志寫到redo log buffer是很快的;wirte到page cache也很快,但是持久化到磁盤的速度就慢多了。
          為了控制redo log的寫入策略,Innodb根據(jù)innodb_flush_log_at_trx_commit參數(shù)不同的取值采用不同的策略,它有三種不同的取值:
            1. 設(shè)置為0時,表示每次事務(wù)提交時都只是把redo log留在redo log buffer 中 ;

            2. 設(shè)置為1時,表示每次事務(wù)提交時都將 redo log 直接持久化到磁盤;

            3. 設(shè)置為2時,表示每次事務(wù)提交時都只是把redo log 寫到page cache。
          三種模式下,0的性能最好,但是不安全,MySQL進程一旦崩潰會導(dǎo)致丟失一秒的數(shù)據(jù)。1的安全性最高,但是對性能影響最大,2的話主要由操作系統(tǒng)自行控制刷磁盤的時間,如果僅僅是MySQL宕機,對數(shù)據(jù)不會產(chǎn)生影響,如果是主機異常宕機了,同樣會丟失數(shù)據(jù)。

          10. 高并發(fā)下如何設(shè)計秒殺系統(tǒng)?

          設(shè)計一個秒殺系統(tǒng),需要考慮這些問題:
          如何解決這些問題呢?
          • 頁面靜態(tài)化
          • 按鈕至灰控制
          • 服務(wù)單一職責(zé)
          • 秒殺鏈接加鹽
          • 限流
          • 分布式鎖
          • MQ異步處理
          • 限流&降級&熔斷
          頁面靜態(tài)化
          秒殺活動的頁面,大多數(shù)內(nèi)容都是固定不變的,如商品名稱,商品圖片等等,可以對活動頁面做靜態(tài)化處理,減少訪問服務(wù)端的請求。秒殺用戶會分布在全國各地,有的在上海,有的在深圳,地域相差很遠,網(wǎng)速也各不相同。為了讓用戶最快訪問到活動頁面,可以使用CDN(Content Delivery Network,內(nèi)容分發(fā)網(wǎng)絡(luò))。CDN可以讓用戶就近獲取所需內(nèi)容。
          按鈕至灰控制
          秒殺活動開始前,按鈕一般需要置灰的。只有時間到了,才能變得可以點擊。這是防止,秒殺用戶在時間快到的前幾秒,瘋狂請求服務(wù)器,然后秒殺時間點還沒到,服務(wù)器就自己掛了。
          服務(wù)單一職責(zé)
          我們都知道微服務(wù)設(shè)計思想,也就是把各個功能模塊拆分,功能那個類似的放一起,再用分布式的部署方式。
          如用戶登錄相關(guān)的,就設(shè)計個用戶服務(wù),訂單相關(guān)的就搞個訂單服務(wù),再到禮物相關(guān)的就搞個禮物服務(wù)等等。那么,秒殺相關(guān)的業(yè)務(wù)邏輯也可以放到一起,搞個秒殺服務(wù),單獨給它搞個秒殺數(shù)據(jù)庫。
          服務(wù)單一職責(zé)有個好處:如果秒殺沒抗住高并發(fā)的壓力,秒殺庫崩了,服務(wù)掛了,也不會影響到系統(tǒng)的其他服務(wù)。
          秒殺鏈接加鹽
          鏈接如果明文暴露的話,會有人獲取到請求Url,提前秒殺了。因此,需要給秒殺鏈接加鹽??梢园裊RL動態(tài)化,如通過MD5加密算法加密隨機的字符串去做url。
          限流
          一般有兩種方式限流:nginx限流和redis限流。
          • 為了防止某個用戶請求過于頻繁,我們可以對同一用戶限流;
          • 為了防止黃牛模擬幾個用戶請求,我們可以對某個IP進行限流;
          • 為了防止有人使用代理,每次請求都更換IP請求,我們可以對接口進行限流。
          • 為了防止瞬時過大的流量壓垮系統(tǒng),還可以使用阿里的Sentinel、Hystrix組件進行限流。
          分布式鎖
          可以使用redis分布式鎖解決超賣問題。
          使用Redis的SET EX PX NX + 校驗唯一隨機值,再刪除釋放鎖。
          if(jedis.set(key_resource_id, uni_request_id, "NX""EX", 100s) == 1){ //加鎖
              try {
                  do something  //業(yè)務(wù)處理
              }catch(){
            }
            finally {
                 //判斷是不是當(dāng)前線程加的鎖,是才釋放
                 if (uni_request_id.equals(jedis.get(key_resource_id))) {
                  jedis.del(lockKey); //釋放鎖
                  }
              }
          }
          在這里,判斷是不是當(dāng)前線程加的鎖和釋放鎖不是一個原子操作。如果調(diào)用jedis.del()釋放鎖的時候,可能這把鎖已經(jīng)不屬于當(dāng)前客戶端,會解除他人加的鎖。
          為了更嚴謹,一般也是用lua腳本代替。lua腳本如下:
          if redis.call('get',KEYS[1]) == ARGV[1] then 
             return redis.call('del',KEYS[1]) 
          else
             return 0
          end;
          MQ異步處理
          如果瞬間流量特別大,可以使用消息隊列削峰,異步處理。用戶請求過來的時候,先放到消息隊列,再拿出來消費。
          限流&降級&熔斷
          • 限流,就是限制請求,防止過大的請求壓垮服務(wù)器;
          • 降級,就是秒殺服務(wù)有問題了,就降級處理,不要影響別的服務(wù);
          • 熔斷,服務(wù)有問題就熔斷,一般熔斷降級是一起出現(xiàn)。

          參考資料

          [1]

          五大常見的MySQL高可用方案: https://zhuanlan.zhihu.com/p/25960208

          [2]

          讀寫分離數(shù)據(jù)庫如何保持數(shù)據(jù)一致性: https://blog.csdn.net/baidu_36161424/article/details/107712388

          [3]

          《我們一起進大廠》系列-秒殺系統(tǒng)設(shè)計: https://juejin.cn/post/6844903999083151374#heading-11

          [4]

          《極客時間:MySQL45講實戰(zhàn)》: http://gk.link/a/10vPr

          [5]

          MySQL是如何保證不丟數(shù)據(jù)的(一): https://cloud.tencent.com/developer/article/1674625


          有道無術(shù),術(shù)可成;有術(shù)無道,止于術(shù)

          歡迎大家關(guān)注Java之道公眾號


          好文章,我在看??

          瀏覽 69
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <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及片 | 操熟女网站| 亚洲蜜臀AV乱码久久精品蜜桃图片 |