国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

分布式事務(wù),zookeeper,dubbo,rocketmq

這篇具有很好參考價值的文章主要介紹了分布式事務(wù),zookeeper,dubbo,rocketmq。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

1.1????????什么是CAP理論

CAP理論是分布式領(lǐng)域中非常重要的一個指導理論,C(Consistency)表示強一致性,A(Availability)表示可用性,P(Partition Tolerance)表示分區(qū)容錯性,CAP理論指出在目前的硬件條件下,一個分布式系統(tǒng)是必須要保證分區(qū)容錯性的,而在這個前提下,分布式系統(tǒng)要么保證CP,要么保證AP,無法同時保證CAP。

分區(qū)容錯性表示,一個系統(tǒng)雖然是分布式的,但是對外看上去應(yīng)該是一個整體,不能由于分布式系統(tǒng)內(nèi)部的某個結(jié)點掛點,或網(wǎng)絡(luò)出現(xiàn)了故障,而導致系統(tǒng)對外出現(xiàn)異常。所以,對于分布式系統(tǒng)而言是一定要保證分區(qū)容錯性的。

強一致性表示,一個分布式系統(tǒng)中各個結(jié)點之間能及時的同步數(shù)據(jù),在數(shù)據(jù)同步過程中,是不能對外提供服務(wù)的,不然就會造成數(shù)據(jù)不一致,所以強一致性和可用性是不能同時滿足的。

可用性表示,一個分布式系統(tǒng)對外要保證可用。

1.2????????什么是BASE理論

由于不能同時滿足CAP,所以出現(xiàn)了BASE理論:

  1. BA:Basically Available,表示基本可用,表示可以允許一定程度的不可用,比如由于系統(tǒng)故障,請求時間變長,或者由于系統(tǒng)故障導致部分非核心功能不可用,都是允許的
  2. S:Soft state:表示分布式系統(tǒng)可以處于一種中間狀態(tài),比如數(shù)據(jù)正在同步
  3. E:Eventually consistent,表示最終一致性,不要求分布式系統(tǒng)數(shù)據(jù)實時達到一致,允許在經(jīng)過一段時間后再達到一致,在達到一致過程中,系統(tǒng)也是可用的

1.3????????什么是RPC

RPC,表示遠程過程調(diào)用,對于Java這種面試對象語言,也可以理解為遠程方法調(diào)用,RPC調(diào)用和HTTP調(diào)用是有區(qū)別的,RPC表示的是一種調(diào)用遠程方法的方式,可以使用HTTP協(xié)議、或直接基于TCP協(xié)議來實現(xiàn)RPC,在Java中,我們可以通過直接使用某個服務(wù)接口的代理對象來執(zhí)行方法,而底層則通過構(gòu)造HTTP請求來調(diào)用遠端的方法,所以,有一種說法是RPC協(xié)議是HTTP協(xié)議之上的一種協(xié)議,也是可以理解的。

1.4????????數(shù)據(jù)一致性模型有哪些

  • 強一致性:當更新操作完成之后,任何多個后續(xù)進程的訪問都會返回最新的更新過的值,這種是對用戶 最友好的,就是用戶上一次寫什么,下一次就保證能讀到什么。根據(jù) CAP理論,這種實現(xiàn)需要犧牲可用性。
  • 弱一致性:系統(tǒng)在數(shù)據(jù)寫入成功之后,不承諾立即可以讀到最新寫入的值,也不會具體的承諾多久之后? 可以讀到。用戶讀到某一操作對系統(tǒng)數(shù)據(jù)的更新需要一段時間,我們稱這段時間為“不一致性窗口”。
  • 最終一致性:最終一致性是弱一致性的特例,強調(diào)的是所有的數(shù)據(jù)副本,在經(jīng)過一段時間的同步之后, 最終都能夠達到一個一致的狀態(tài)。因此,最終一致性的本質(zhì)是需要系統(tǒng)保證最終數(shù)據(jù)能夠達到一致,而 不需要實時保證系統(tǒng)數(shù)據(jù)的強一致性。到達最終一致性的時間 ,就是不一致窗口時間,在沒有故障發(fā)生的前提下,不一致窗口的時間主要受通信延遲,系統(tǒng)負載和復制副本的個數(shù)影響。最終一致性模型根據(jù)其提供的不同保證可以劃分為更多的模型,包括因果一致性和會話一致性等。

1.5????????分布式ID是什么?有哪些解決方案?

在開發(fā)中,我們通常會需要一個唯一ID來標識數(shù)據(jù),如果是單體架構(gòu),我們可以通過數(shù)據(jù)庫的主鍵,或直接在內(nèi)存中維護一個自增數(shù)字來作為ID都是可以的,但對于一個分布式系統(tǒng),就會有可能會出現(xiàn)ID沖突,此時有以下解決方案:

  1. uuid,這種方案復雜度最低,但是會影響存儲空間和性能
  2. 利用單機數(shù)據(jù)庫的自增主鍵,作為分布式ID的生成器,復雜度適中,ID長度較之uuid更短,但是受到單機數(shù)據(jù)庫性能的限制,并發(fā)量大的時候,此方案也不是最優(yōu)方案
  3. 利用redis、zookeeper的特性來生成id,比如redis的自增命令、zookeeper的順序節(jié)點,這種方案和單機數(shù)據(jù)庫(mysql)相比,性能有所提高,可以適當選用
  4. 雪花算法,一切問題如果能直接用算法解決,那就是最合適的,利用雪花算法也可以生成分布式ID,底層原理就是通過某臺機器在某一毫秒內(nèi)對某一個數(shù)字自增,這種方案也能保證分布式架構(gòu)中的系統(tǒng)id唯一,但是只能保證趨勢遞增。業(yè)界存在tinyid、leaf等開源中間件實現(xiàn)了雪花算法。

1.6????????分布式鎖的使用場景是什么?有哪些實現(xiàn)方案?

在單體架構(gòu)中,多個線程都是屬于同一個進程的,所以在線程并發(fā)執(zhí)行時,遇到資源競爭時,可以利用ReentrantLock、synchronized等技術(shù)來作為鎖,來控制共享資源的使用。

而在分布式架構(gòu)中,多個線程是可能處于不同進程中的,而這些線程并發(fā)執(zhí)行遇到資源競爭時,利用ReentrantLock、synchronized等技術(shù)是沒辦法來控制多個進程中的線程的,所以需要分布式鎖,意思就是,需要一個分布式鎖生成器,分布式系統(tǒng)中的應(yīng)用程序都可以來使用這個生成器所提供的鎖,從而達到多個進程中的線程使用同一把鎖。

目前主流的分布式鎖的實現(xiàn)方案有兩種:

  1. zookeeper:利用的是zookeeper的臨時節(jié)點、順序節(jié)點、watch機制來實現(xiàn)的,zookeeper分布式鎖的特點是高一致性,因為zookeeper保證的是CP,所以由它實現(xiàn)的分布式鎖更可靠,不會出現(xiàn)混亂
  2. redis:利用redis的setnx、lua腳本、消費訂閱等機制來實現(xiàn)的,redis分布式鎖的特點是高可用,因為redis保證的是AP,所以由它實現(xiàn)的分布式鎖可能不可靠,不穩(wěn)定(一旦redis中的數(shù)據(jù)出現(xiàn)了不一致),可能會出現(xiàn)多個客戶端同時加到鎖的情況

1.7????????什么是分布式事務(wù)?有哪些實現(xiàn)方案?

在分布式系統(tǒng)中,一次業(yè)務(wù)處理可能需要多個應(yīng)用來實現(xiàn),比如用戶發(fā)送一次下單請求,就涉及到訂單系統(tǒng)創(chuàng)建訂單、庫存系統(tǒng)減庫存,而對于一次下單,訂單創(chuàng)建與減庫存應(yīng)該是要同時成功或同時失敗的,但在分布式系統(tǒng)中,如果不做處理,就很有可能出現(xiàn)訂單創(chuàng)建成功,但是減庫存失敗,那么解決這類問題,就需要用到分布式事務(wù)。常用解決方案有:

  1. 本地消息表:創(chuàng)建訂單時,將減庫存消息加入在本地事務(wù)中,一起提交到數(shù)據(jù)庫存入本地消息表,然后調(diào)用庫存系統(tǒng),如果調(diào)用成功則修改本地消息狀態(tài)為成功,如果調(diào)用庫存系統(tǒng)失敗,則由后臺定時任務(wù)從本地消息表中取出未成功的消息,重試調(diào)用庫存系統(tǒng)
  2. 消息隊列:目前RocketMQ中支持事務(wù)消息,它的工作原理是:
    1. 生產(chǎn)者訂單系統(tǒng)先發(fā)送一條half消息到Broker,half消息對消費者而言是不可見的
    2. 再創(chuàng)建訂單,根據(jù)創(chuàng)建訂單成功與否,向Broker發(fā)送commit或rollback
    3. 并且生產(chǎn)者訂單系統(tǒng)還可以提供Broker回調(diào)接口,當Broker發(fā)現(xiàn)一段時間half消息沒有收到任何操作命令,則會主動調(diào)此接口來查詢訂單是否創(chuàng)建成功
    4. 一旦half消息commit了,消費者庫存系統(tǒng)就會來消費,如果消費成功,則消息銷毀,分布式事務(wù)成功結(jié)束
    5. 如果消費失敗,則根據(jù)重試策略進行重試,最后還失敗則進入死信隊列,等待進一步處理
  1. Seata:阿里開源的分布式事務(wù)框架,支持AT、TCC等多種模式,底層都是基于兩階段提交理論來實現(xiàn)的

1.8????????什么是ZAB協(xié)議

ZAB協(xié)議是Zookeeper用來實現(xiàn)一致性的原子廣播協(xié)議,該協(xié)議描述了Zookeeper是如何實現(xiàn)一致性的,分為三個階段:

  1. 領(lǐng)導者選舉階段:從Zookeeper集群中選出一個節(jié)點作為Leader,所有的寫請求都會由Leader節(jié)點來處理
  2. 數(shù)據(jù)同步階段:集群中所有節(jié)點中的數(shù)據(jù)要和Leader節(jié)點保持一致,如果不一致則要進行同步
  3. 請求廣播階段:當Leader節(jié)點接收到寫請求時,會利用兩階段提交來廣播該寫請求,使得寫請求像事務(wù)一樣在其他節(jié)點上執(zhí)行,達到節(jié)點上的數(shù)據(jù)實時一致

但值得注意的是,Zookeeper只是盡量的在達到強一致性,實際上仍然只是最終一致性的。

1.9????????為什么Zookeeper可以用來作為注冊中心

可以利用Zookeeper的臨時節(jié)點和watch機制來實現(xiàn)注冊中心的自動注冊和發(fā)現(xiàn),另外Zookeeper中的數(shù)據(jù)都是存在內(nèi)存中的,并且Zookeeper底層采用了nio,多線程模型,所以Zookeeper的性能也是比較高的,所以可以用來作為注冊中心,但是如果考慮到注冊中心應(yīng)該是注冊可用性的話,那么Zookeeper則不太合適,因為Zookeeper是CP的,它注重的是一致性,所以集群數(shù)據(jù)不一致時,集群將不可用,所以用Redis、Eureka、Nacos來作為注冊中心將更合適。

1.10????????Zookeeper中的領(lǐng)導者選舉的流程是怎樣的?

對于Zookeeper集群,整個集群需要從集群節(jié)點中選出一個節(jié)點作為Leader,大體流程如下:

  1. 集群中各個節(jié)點首先都是觀望狀態(tài)(LOOKING),一開始都會投票給自己,認為自己比較適合作為leader
  2. 然后相互交互投票,每個節(jié)點會收到其他節(jié)點發(fā)過來的選票,然后pk,先比較zxid,zxid大者獲勝,zxid如果相等則比較myid,myid大者獲勝
  3. 一個節(jié)點收到其他節(jié)點發(fā)過來的選票,經(jīng)過PK后,如果PK輸了,則改票,此節(jié)點就會投給zxid或myid更大的節(jié)點,并將選票放入自己的投票箱中,并將新的選票發(fā)送給其他節(jié)點
  4. 如果pk是平局則將接收到的選票放入自己的投票箱中
  5. 如果pk贏了,則忽略所接收到的選票
  6. 當然一個節(jié)點將一張選票放入到自己的投票箱之后,就會從投票箱中統(tǒng)計票數(shù),看是否超過一半的節(jié)點都和自己所投的節(jié)點是一樣的,如果超過半數(shù),那么則認為當前自己所投的節(jié)點是leader
  7. 集群中每個節(jié)點都會經(jīng)過同樣的流程,pk的規(guī)則也是一樣的,一旦改票就會告訴給其他服務(wù)器,所以最終各個節(jié)點中的投票箱中的選票也將是一樣的,所以各個節(jié)點最終選出來的leader也是一樣的,這樣集群的leader就選舉出來了

1.11????????Zookeeper集群中節(jié)點之間數(shù)據(jù)是如何同步的

  1. 首先集群啟動時,會先進行領(lǐng)導者選舉,確定哪個節(jié)點是Leader,哪些節(jié)點是Follower和Observer
  2. 然后Leader會和其他節(jié)點進行數(shù)據(jù)同步,采用發(fā)送快照和發(fā)送Diff日志的方式
  3. 集群在工作過程中,所有的寫請求都會交給Leader節(jié)點來進行處理,從節(jié)點只能處理讀請求
  4. Leader節(jié)點收到一個寫請求時,會通過兩階段機制來處理
  5. Leader節(jié)點會將該寫請求對應(yīng)的日志發(fā)送給其他Follower節(jié)點,并等待Follower節(jié)點持久化日志成功
  6. Follower節(jié)點收到日志后會進行持久化,如果持久化成功則發(fā)送一個Ack給Leader節(jié)點
  7. 當Leader節(jié)點收到半數(shù)以上的Ack后,就會開始提交,先更新Leader節(jié)點本地的內(nèi)存數(shù)據(jù)
  8. 然后發(fā)送commit命令給Follower節(jié)點,F(xiàn)ollower節(jié)點收到commit命令后就會更新各自本地內(nèi)存數(shù)據(jù)
  9. 同時Leader節(jié)點還是將當前寫請求直接發(fā)送給Observer節(jié)點,Observer節(jié)點收到Leader發(fā)過來的寫請求后直接執(zhí)行更新本地內(nèi)存數(shù)據(jù)
  10. 最后Leader節(jié)點返回客戶端寫請求響應(yīng)成功
  11. 通過同步機制和兩階段提交機制來達到集群中節(jié)點數(shù)據(jù)一致

1.12????????Dubbo支持哪些負載均衡策略

  1. 隨機:從多個服務(wù)提供者隨機選擇一個來處理本次請求,調(diào)用量越大則分布越均勻,并支持按權(quán)重設(shè)置隨機概率
  2. 輪詢:依次選擇服務(wù)提供者來處理請求, 并支持按權(quán)重進行輪詢,底層采用的是平滑加權(quán)輪詢算法
  3. 最小活躍調(diào)用數(shù):統(tǒng)計服務(wù)提供者當前正在處理的請求,下次請求過來則交給活躍數(shù)最小的服務(wù)器來處理
  4. 一致性哈希:相同參數(shù)的請求總是發(fā)到同一個服務(wù)提供者

1.13????????Dubbo是如何完成服務(wù)導出的?

  1. 首先Dubbo會將程序員所使用的@DubboService注解或@Service注解進行解析得到程序員所定義的服務(wù)參數(shù),包括定義的服務(wù)名、服務(wù)接口、服務(wù)超時時間、服務(wù)協(xié)議等等,得到一個ServiceBean。
  2. 然后調(diào)用ServiceBean的export方法進行服務(wù)導出
  3. 然后將服務(wù)信息注冊到注冊中心,如果有多個協(xié)議,多個注冊中心,那就將服務(wù)按單個協(xié)議,單個注冊中心進行注冊
  4. 將服務(wù)信息注冊到注冊中心后,還會綁定一些監(jiān)聽器,監(jiān)聽動態(tài)配置中心的變更
  5. 還會根據(jù)服務(wù)協(xié)議啟動對應(yīng)的Web服務(wù)器或網(wǎng)絡(luò)框架,比如Tomcat、Netty等

1.14????????Dubbo是如何完成服務(wù)引入的?

  1. 當程序員使用@Reference注解來引入一個服務(wù)時,Dubbo會將注解和服務(wù)的信息解析出來,得到當前所引用的服務(wù)名、服務(wù)接口是什么
  2. 然后從注冊中心進行查詢服務(wù)信息,得到服務(wù)的提供者信息,并存在消費端的服務(wù)目錄中
  3. 并綁定一些監(jiān)聽器用來監(jiān)聽動態(tài)配置中心的變更
  4. 然后根據(jù)查詢得到的服務(wù)提供者信息生成一個服務(wù)接口的代理對象,并放入Spring容器中作為Bean

1.15????????Dubbo的架構(gòu)設(shè)計是怎樣的?

Dubbo中的架構(gòu)設(shè)計是非常優(yōu)秀的,分為了很多層次,并且每層都是可以擴展的,比如:

  1. Proxy服務(wù)代理層,支持JDK動態(tài)代理、javassist等代理機制
  2. Registry注冊中心層,支持Zookeeper、Redis等作為注冊中心
  3. Protocol遠程調(diào)用層,支持Dubbo、Http等調(diào)用協(xié)議
  4. Transport網(wǎng)絡(luò)傳輸層,支持netty、mina等網(wǎng)絡(luò)傳輸框架
  5. Serialize數(shù)據(jù)序列化層,支持JSON、Hessian等序列化機制
1.15.1????????各層說明
  • config 配置層:對外配置接口,以?ServiceConfig,?ReferenceConfig?為中心,可以直接初始化配置類,也可以通過 spring 解析配置生成配置類
  • proxy 服務(wù)代理層:服務(wù)接口透明代理,生成服務(wù)的客戶端 Stub 和服務(wù)器端 Skeleton, 以?ServiceProxy?為中心,擴展接口為?ProxyFactory
  • registry 注冊中心層:封裝服務(wù)地址的注冊與發(fā)現(xiàn),以服務(wù) URL 為中心,擴展接口為?RegistryFactory,?Registry,?RegistryService
  • cluster 路由層:封裝多個提供者的路由及負載均衡,并橋接注冊中心,以?Invoker?為中心,擴展接口為?Cluster,?Directory,?Router,?LoadBalance
  • monitor 監(jiān)控層:RPC 調(diào)用次數(shù)和調(diào)用時間監(jiān)控,以?Statistics?為中心,擴展接口為?MonitorFactory,?Monitor,?MonitorService
  • protocol 遠程調(diào)用層:封裝 RPC 調(diào)用,以?Invocation,?Result?為中心,擴展接口為?Protocol,?Invoker,?Exporter
  • exchange 信息交換層:封裝請求響應(yīng)模式,同步轉(zhuǎn)異步,以?Request,?Response?為中心,擴展接口為?Exchanger,?ExchangeChannel,?ExchangeClient,?ExchangeServer
  • transport 網(wǎng)絡(luò)傳輸層:抽象 mina 和 netty 為統(tǒng)一接口,以?Message?為中心,擴展接口為?Channel,?Transporter,?Client,?Server,?Codec
  • serialize 數(shù)據(jù)序列化層:可復用的一些工具,擴展接口為?Serialization,?ObjectInput,?ObjectOutput,?ThreadPool
1.15.2????????關(guān)系說明
  • 在 RPC 中,Protocol 是核心層,也就是只要有 Protocol + Invoker + Exporter 就可以完成非透明的 RPC 調(diào)用,然后在 Invoker 的主過程上 Filter 攔截點。
  • 圖中的 Consumer 和 Provider 是抽象概念,只是想讓看圖者更直觀的了解哪些類分屬于客戶端與服務(wù)器端,不用 Client 和 Server 的原因是 Dubbo 在很多場景下都使用 Provider, Consumer, Registry, Monitor 劃分邏輯拓普節(jié)點,保持統(tǒng)一概念。
  • 而 Cluster 是外圍概念,所以 Cluster 的目的是將多個 Invoker 偽裝成一個 Invoker,這樣其它人只要關(guān)注 Protocol 層 Invoker 即可,加上 Cluster 或者去掉 Cluster 對其它層都不會造成影響,因為只有一個提供者時,是不需要 Cluster 的。
  • Proxy 層封裝了所有接口的透明化代理,而在其它層都以 Invoker 為中心,只有到了暴露給用戶使用時,才用 Proxy 將 Invoker 轉(zhuǎn)成接口,或?qū)⒔涌趯崿F(xiàn)轉(zhuǎn)成 Invoker,也就是去掉 Proxy 層 RPC 是可以 Run 的,只是不那么透明,不那么看起來像調(diào)本地服務(wù)一樣調(diào)遠程服務(wù)。
  • 而 Remoting 實現(xiàn)是 Dubbo 協(xié)議的實現(xiàn),如果你選擇 RMI 協(xié)議,整個 Remoting 都不會用上,Remoting 內(nèi)部再劃為 Transport 傳輸層和 Exchange 信息交換層,Transport 層只負責單向消息傳輸,是對 Mina, Netty, Grizzly 的抽象,它也可以擴展 UDP 傳輸,而 Exchange 層是在傳輸層之上封裝了 Request-Response 語義。
  • Registry 和 Monitor 實際上不算一層,而是一個獨立的節(jié)點,只是為了全局概覽,用層的方式畫在一起。

cap 選舉,分布式,zookeeper,dubbo

1.16????????負載均衡算法有哪些

1、輪詢法:將請求按順序輪流地分配到后端服務(wù)器上,它均衡地對待后端的每一臺服務(wù)器,而不關(guān)心服務(wù)器實際的連接數(shù)和當前的系統(tǒng)負載。

2、隨機法:通過系統(tǒng)的隨機算法,根據(jù)后端服務(wù)器的列表大小值來隨機選取其中的一臺服務(wù)器進行訪問。由概率統(tǒng)計理論可以得知,隨著客戶端調(diào)用服務(wù)端的次數(shù)增多,其實際效果越來越接近于平均分配調(diào)用量到后端的每一臺服務(wù)器,也就是輪詢的結(jié)果。

3、源地址哈希法:源地址哈希的思想是根據(jù)獲取客戶端的IP地址,通過哈希函數(shù)計算得到的一個數(shù)值,用該數(shù)值對服務(wù)器列表的大小進行取模運算,得到的結(jié)果便是客服端要訪問服務(wù)器的序號。采用源地址哈希法進行負載均衡,同一IP地址的客戶端,當后端服務(wù)器列表不變時,它每次都會映射到同一臺后端服務(wù)器進行訪問。

4、加權(quán)輪詢法:不同的后端服務(wù)器可能機器的配置和當前系統(tǒng)的負載并不相同,因此它們的抗壓能力也不相同。給配置高、負載低的機器配置更高的權(quán)重,讓其處理更多的請;而配置低、負載高的機器,給其分配較低的權(quán)重,降低其系統(tǒng)負載,加權(quán)輪詢能很好地處理這一問題,并將請求順序且按照權(quán)重分配到后端。

5、加權(quán)隨機法:與加權(quán)輪詢法一樣,加權(quán)隨機法也根據(jù)后端機器的配置,系統(tǒng)的負載分配不同的權(quán)重。不同的是,它是按照權(quán)重隨機請求后端服務(wù)器,而非順序。

6、最小連接數(shù)法:最小連接數(shù)算法比較靈活和智能,由于后端服務(wù)器的配置不盡相同,對于請求的處理有快有慢,它是根據(jù)后端服務(wù)器當前的連接情況,動態(tài)地選取其中當前積壓連接數(shù)最少的一臺服務(wù)器來處理當前的請求,盡可能地提高后端服務(wù)的利用效率,將負責合理地分流到每一臺服務(wù)器。

1.17????????分布式架構(gòu)下,Session 共享有什么方案

1、采用無狀態(tài)服務(wù),拋棄session

2、存入cookie(有安全風險)

3、服務(wù)器之間進行 Session 同步,這樣可以保證每個服務(wù)器上都有全部的 Session 信息,不過當服務(wù)器數(shù)量比較多的時候,同步是會有延遲甚至同步失敗;

4、 IP 綁定策略,使用 Nginx (或其他復雜均衡軟硬件)中的 IP 綁定策略,同一個 IP 只能在指定的同一個機器訪問,但是這樣做失去了負載均衡的意義,當掛掉一臺服務(wù)器的時候,會影響一批用戶的使用,風險很大;

5、使用 Redis 存儲

把 Session 放到 Redis 中存儲,雖然架構(gòu)上變得復雜,并且需要多訪問一次 Redis ,但是這種方案帶來的好處也是很大的:

  • 實現(xiàn)了 Session 共享;
  • 可以水平擴展(增加 Redis 服務(wù)器);
  • 服務(wù)器重啟 Session 不丟失(不過也要注意 Session 在 Redis 中的刷新/失效機制);
  • 不僅可以跨服務(wù)器 Session 共享,甚至可以跨平臺(例如網(wǎng)頁端和 APP 端)。

1.18????????如何實現(xiàn)接口的冪等性

  • 唯一id。每次操作,都根據(jù)操作和內(nèi)容生成唯一的id,在執(zhí)行之前先判斷id是否存在,如果不存在則執(zhí)行后續(xù)操作,并且保存到數(shù)據(jù)庫或者redis等。
  • 服務(wù)端提供發(fā)送token的接口,業(yè)務(wù)調(diào)用接口前先獲取token,然后調(diào)用業(yè)務(wù)接口請求時,把token攜帶過去,務(wù)器判斷token是否存在redis中,存在表示第一次請求,可以繼續(xù)執(zhí)行業(yè)務(wù),執(zhí)行業(yè)務(wù)完成后,最后需要把redis中的token刪除
  • 建去重表。將業(yè)務(wù)中有唯一標識的字段保存到去重表,如果表中存在,則表示已經(jīng)處理過了
  • 版本控制。增加版本號,當版本號符合時,才能更新數(shù)據(jù)
  • 狀態(tài)控制。例如訂單有狀態(tài)已支付 未支付 支付中 支付失敗,當處于未支付的時候才允許修改為支付中等

1.19????????簡述zk的命名服務(wù)、配置管理、集群管理

命名服務(wù):

通過指定的名字來獲取資源或者服務(wù)地址。Zookeeper可以創(chuàng)建一個全局唯一的路徑,這個路徑就可以作為一個名字。被命名的實體可以是集群中的機器,服務(wù)的地址,或者是遠程的對象等。一些分布式服務(wù)框架(RPC、RMI)中的服務(wù)地址列表,通過使用命名服務(wù),客戶端應(yīng)用能夠根據(jù)特定的名字來獲取資源的實體、服務(wù)地址和提供者信息等

配置管理:

實際項目開發(fā)中,經(jīng)常使用.properties或者xml需要配置很多信息,如數(shù)據(jù)庫連接信息、fps地址端口等等。程序分布式部署時,如果把程序的這些配置信息保存在zk的znode節(jié)點下,當你要修改配置,即znode會發(fā)生變化時,可以通過改變zk中某個目錄節(jié)點的內(nèi)容,利用watcher通知給各個客戶端,從而更改配置。

集群管理:

集群管理包括集群監(jiān)控和集群控制,就是監(jiān)控集群機器狀態(tài),剔除機器和加入機器。zookeeper可以方便集群機器的管理,它可以實時監(jiān)控znode節(jié)點的變化,一旦發(fā)現(xiàn)有機器掛了,該機器就會與zk斷開連接,對應(yīng)的臨時目錄節(jié)點會被刪除,其他所有機器都收到通知。新機器加入也是類似。

1.20????????講下Zookeeper中的watch機制

客戶端,可以通過在znode上設(shè)置watch,實現(xiàn)實時監(jiān)聽znode的變化

Watch事件是一個一次性的觸發(fā)器,當被設(shè)置了Watch的數(shù)據(jù)發(fā)生了改變的時候,則服務(wù)器將這個改變發(fā)送給設(shè)置了Watch的客戶端

  • 父節(jié)點的創(chuàng)建,修改,刪除都會觸發(fā)Watcher事件。
  • 子節(jié)點的創(chuàng)建,刪除會觸發(fā)Watcher事件。

一次性:一旦被觸發(fā)就會移除,再次使用需要重新注冊,因為每次變動都需要通知所有客戶端,一次性可以減輕壓力,3.6.0默認持久遞歸,可以觸發(fā)多次

輕量:只通知發(fā)生了事件,不會告知事件內(nèi)容,減輕服務(wù)器和帶寬壓力

Watcher 機制包括三個角色:客戶端線程、客戶端的 WatchManager 以及 ZooKeeper 服務(wù)器

  1. 客戶端向 ZooKeeper 服務(wù)器注冊一個 Watcher 監(jiān)聽,?
  2. 把這個監(jiān)聽信息存儲到客戶端的 WatchManager 中?
  3. 當 ZooKeeper 中的節(jié)點發(fā)生變化時,會通知客戶端,客戶端會調(diào)用相應(yīng) Watcher 對象中的回調(diào)方法。watch回調(diào)是串行同步的?

1.21????????Zookeeper和Eureka的區(qū)別

zk:CP設(shè)計(強一致性),目標是一個分布式的協(xié)調(diào)系統(tǒng),用于進行資源的統(tǒng)一管理。當節(jié)點crash后,需要進行l(wèi)eader的選舉,在這個期間內(nèi),zk服務(wù)是不可用的。

eureka:AP設(shè)計(高可用),目標是一個服務(wù)注冊發(fā)現(xiàn)系統(tǒng),專門用于微服務(wù)的服務(wù)發(fā)現(xiàn)注冊。

Eureka各個節(jié)點都是平等的,幾個節(jié)點掛掉不會影響正常節(jié)點的工作,剩余的節(jié)點依然可以提供注冊和查詢服務(wù)。而Eureka的客戶端在向某個Eureka注冊時如果發(fā)現(xiàn)連接失敗,會自動切換至其他節(jié)點,只要有一臺Eureka還在,就能保證注冊服務(wù)可用(保證可用性),只不過查到的信息可能不是最新的(不保證強一致性)

同時當eureka的服務(wù)端發(fā)現(xiàn)85%以上的服務(wù)都沒有心跳的話,它就會認為自己的網(wǎng)絡(luò)出了問題,就不會從服務(wù)列表中刪除這些失去心跳的服務(wù),同時eureka的客戶端也會緩存服務(wù)信息。eureka對于服務(wù)注冊發(fā)現(xiàn)來說是非常好的選擇。

1.22????????存儲拆分后如何解決唯一主鍵問題

  • UUID:簡單、性能好,沒有順序,沒有業(yè)務(wù)含義,存在泄漏mac地址的風險
  • 數(shù)據(jù)庫主鍵:實現(xiàn)簡單,單調(diào)遞增,具有一定的業(yè)務(wù)可讀性,強依賴db、存在性能瓶頸,存在暴露業(yè)務(wù)?信息的風險
  • redis,mongodb,zk等中間件:增加了系統(tǒng)的復雜度和穩(wěn)定性?
  • 雪花算法

1.23????????雪花算法原理

cap 選舉,分布式,zookeeper,dubbo

第一位符號位固定為0,41位時間戳,10位workId,12位序列號,位數(shù)可以有不同實現(xiàn)。

優(yōu)點:每個毫秒值包含的ID值很多,不夠可以變動位數(shù)來增加,性能佳(依賴workId的實現(xiàn))。時間戳值在高位,中間是固定的機器碼,自增的序列在低位,整個ID是趨勢遞增的。能夠根據(jù)業(yè)務(wù)場景數(shù)據(jù)庫節(jié)點布置靈活調(diào)整bit位劃分,靈活度高。

缺點:強依賴于機器時鐘,如果時鐘回撥,會導致重復的ID生成,所以一般基于此的算法發(fā)現(xiàn)時鐘回 撥,都會拋異常處理,阻止ID生成,這可能導致服務(wù)不可用。

1.24????????如何解決不使用分區(qū)鍵的查詢問題

  • 映射:將查詢條件的字段與分區(qū)鍵進行映射,建一張單獨的表維護(使用覆蓋索引)或者在緩存中維 護
  • 基因法:分區(qū)鍵的后x個bit位由查詢字段進行hash后占用,分區(qū)鍵直接取x個bit位獲取分區(qū),查詢字段進行hash獲取分區(qū),適合非分區(qū)鍵查詢字段只有一個的情況
  • 冗余:查詢字段冗余存儲

1.25????????Spring Cloud有哪些常用組件,作用是什么?

  1. Eureka:注冊中心
  2. Nacos:注冊中心、配置中心
  3. Consul:注冊中心、配置中心
  4. Spring Cloud Config:配置中心
  5. Feign/OpenFeign:RPC調(diào)用
  6. Kong:服務(wù)網(wǎng)關(guān)
  7. Zuul:服務(wù)網(wǎng)關(guān)
  8. Spring Cloud Gateway:服務(wù)網(wǎng)關(guān)
  9. Ribbon:負載均衡
  10. Spring CLoud Sleuth:鏈路追蹤
  11. Zipkin:鏈路追蹤
  12. Seata:分布式事務(wù)
  13. Dubbo:RPC調(diào)用
  14. Sentinel:服務(wù)熔斷
  15. Hystrix:服務(wù)熔斷

1.26????????分布式系統(tǒng)中常用的緩存方案有哪些

  • 客戶端緩存:頁面和瀏覽器緩存,APP緩存,H5緩存,localStorage 和 sessionStorage CDN緩存:內(nèi)容存儲:數(shù)據(jù)的緩存,內(nèi)容分發(fā):負載均衡
  • nginx緩存:靜態(tài)資源
  • 服務(wù)端緩存:本地緩存,外部緩存
  • 數(shù)據(jù)庫緩存:持久層緩存(mybatis,hibernate多級緩存),mysql查詢緩存 操作系統(tǒng)緩存:PageCache、BufferCache

1.27????????分布式緩存尋址算法

  • hash算法:根據(jù)key進行hash函數(shù)運算、結(jié)果對分片數(shù)取模,確定分片 適合固定分片數(shù)的場景,擴展分片或者減少分片時,所有數(shù)據(jù)都需要重新計算分片、存儲
  • 一致性hash:將整個hash值得區(qū)間組織成一個閉合的圓環(huán),計算每臺服務(wù)器的hash值、映射到圓環(huán)中。使用相同的hash算法計算數(shù)據(jù)的hash值,映射到圓環(huán),順時針尋找,找到的第一個服務(wù)器就是數(shù)據(jù)存儲的服務(wù)器。新增及減少節(jié)點時只會影響節(jié)點到他逆時針最近的一個服務(wù)器之間的值 存在hash環(huán)傾斜的問題,即服務(wù)器分布不均勻,可以通過虛擬節(jié)點解決
  • hash slot:將數(shù)據(jù)與服務(wù)器隔離開,數(shù)據(jù)與slot映射,slot與服務(wù)器映射,數(shù)據(jù)進行hash決定存放的slot,新增及刪除節(jié)點時,將slot進行遷移即可

1.28????????Spring Cloud和Dubbo有哪些區(qū)別?

Spring Cloud是一個微服務(wù)框架,提供了微服務(wù)領(lǐng)域中的很多功能組件,Dubbo一開始是一個RPC調(diào)用框架,核心是解決服務(wù)調(diào)用間的問題,Spring Cloud是一個大而全的框架,Dubbo則更側(cè)重于服務(wù)調(diào)用,所以Dubbo所提供的功能沒有Spring Cloud全面,但是Dubbo的服務(wù)調(diào)用性能比Spring Cloud高,不過Spring Cloud和Dubbo并不是對立的,是可以結(jié)合起來一起使用的。

1.29????????什么是服務(wù)雪崩?什么是服務(wù)限流?

  1. 當服務(wù)A調(diào)用服務(wù)B,服務(wù)B調(diào)用C,此時大量請求突然請求服務(wù)A,假如服務(wù)A本身能抗住這些請求,但是如果服務(wù)C抗不住,導致服務(wù)C請求堆積,從而服務(wù)B請求堆積,從而服務(wù)A不可用,這就是服務(wù)雪崩,解決方式就是服務(wù)降級和服務(wù)熔斷。
  2. 服務(wù)限流是指在高并發(fā)請求下,為了保護系統(tǒng),可以對訪問服務(wù)的請求進行數(shù)量上的限制,從而防止系統(tǒng)不被大量請求壓垮,在秒殺中,限流是非常重要的。

1.30????????什么是服務(wù)熔斷?什么是服務(wù)降級?區(qū)別是什么?

  1. 服務(wù)熔斷是指,當服務(wù)A調(diào)用的某個服務(wù)B不可用時,上游服務(wù)A為了保證自己不受影響,從而不再調(diào)用服務(wù)B,直接返回一個結(jié)果,減輕服務(wù)A和服務(wù)B的壓力,直到服務(wù)B恢復。
  2. 服務(wù)降級是指,當發(fā)現(xiàn)系統(tǒng)壓力過載時,可以通過關(guān)閉某個服務(wù),或限流某個服務(wù)來減輕系統(tǒng)壓力,這就是服務(wù)降級。

相同點:

  1. 都是為了防止系統(tǒng)崩潰
  2. 都讓用戶體驗到某些功能暫時不可用

不同點:熔斷是下游服務(wù)故障觸發(fā)的,降級是為了降低系統(tǒng)負載

1.31????????SOA、分布式、微服務(wù)之間有什么關(guān)系和區(qū)別?

  1. 分布式架構(gòu)是指將單體架構(gòu)中的各個部分拆分,然后部署不同的機器或進程中去,SOA和微服務(wù)基本上都是分布式架構(gòu)的
  2. SOA是一種面向服務(wù)的架構(gòu),系統(tǒng)的所有服務(wù)都注冊在總線上,當調(diào)用服務(wù)時,從總線上查找服務(wù)信息,然后調(diào)用
  3. 微服務(wù)是一種更徹底的面向服務(wù)的架構(gòu),將系統(tǒng)中各個功能個體抽成一個個小的應(yīng)用程序,基本保持一個應(yīng)用對應(yīng)的一個服務(wù)的架構(gòu)

1.32????????怎么拆分微服務(wù)?

拆分微服務(wù)的時候,為了盡量保證微服務(wù)的穩(wěn)定,會有一些基本的準則:

  1. 微服務(wù)之間盡量不要有業(yè)務(wù)交叉。
  2. 微服務(wù)之前只能通過接口進行服務(wù)調(diào)用,而不能繞過接口直接訪問對方的數(shù)據(jù)。
  3. 高內(nèi)聚,低耦合。

1.33????????怎樣設(shè)計出高內(nèi)聚、低耦合的微服務(wù)?

高內(nèi)聚低耦合,是一種從上而下指導微服務(wù)設(shè)計的方法。實現(xiàn)高內(nèi)聚低耦合的工具主要有 同步的接口調(diào)用 和 異步的事件驅(qū)動 兩種方式。

1.34????????有沒有了解過DDD領(lǐng)域驅(qū)動設(shè)計?

什么是DDD: 在2004年,由Eric Evans提出了, DDD是面對軟件復雜之道。Domain-Driven- Design –Tackling Complexity in the Heart of Software?

大泥團: 不利于微服務(wù)的拆分。大泥團結(jié)構(gòu)拆分出來的微服務(wù)依然是泥團機構(gòu),當服務(wù)業(yè)務(wù)逐漸復雜,這個泥團又會膨脹成為大泥團。

DDD只是一種方法論,沒有一個穩(wěn)定的技術(shù)框架。DDD要求領(lǐng)域是跟技術(shù)無關(guān)、跟存儲無關(guān)、跟通信無關(guān)。

1.34????????什么是中臺?

所謂中臺,就是將各個業(yè)務(wù)線中可以復用的一些功能抽取出來,剝離個性,提取共性,形成一些可復用的組件。?

大體上,中臺可以分為三類 業(yè)務(wù)中臺、數(shù)據(jù)中臺和技術(shù)中臺。大數(shù)據(jù)殺熟-數(shù)據(jù)中臺?

中臺跟DDD結(jié)合: DDD會通過限界上下文將系統(tǒng)拆分成一個一個的領(lǐng)域, 而這種限界上下文,天生就成了中臺之間的邏輯屏障。

DDD在技術(shù)與資源調(diào)度方面都能夠給中臺建設(shè)提供不錯的指導。

DDD分為戰(zhàn)略設(shè)計和戰(zhàn)術(shù)設(shè)計。 上層的戰(zhàn)略設(shè)計能夠很好的指導中臺劃分,下層的戰(zhàn)術(shù)設(shè)計能夠很好的指導微服務(wù)搭建。

1.35????????你的項目中是怎么保證微服務(wù)敏捷開發(fā)的?

  • 開發(fā)運維一體化。
  • 敏捷開發(fā): 目的就是為了提高團隊的交付效率,快速迭代,快速試錯
  • 每個月固定發(fā)布新版本,以分支的形式保存到代碼倉庫中??焖偃肼?。任務(wù)面板、站立會議。團隊人員靈活流動,同時形成各個專家代表
  • 測試環(huán)境- 生產(chǎn)環(huán)境 -開發(fā)測試環(huán)境SIT-集成測試環(huán)境-壓測環(huán)境STR-預投產(chǎn)環(huán)境-生產(chǎn)環(huán)境PRD
  • 晨會、周會、需求拆分會

二????????RocketMQ?

1.36????????如何進行消息隊列選型?

  • Kafka:
    • 優(yōu)點: 吞吐量非常大,性能非常好,集群高可用。
    • 缺點:會丟數(shù)據(jù),功能比較單一。
    • 使用場景:日志分析、大數(shù)據(jù)采集
  • RabbitMQ:
    • 優(yōu)點: 消息可靠性高,功能全面。
    • 缺點:吞吐量比較低,消息積累會嚴重影響性能。erlang語言不好定制。
    • 使用場景:小規(guī)模場景。
  • RocketMQ:
    • 優(yōu)點:高吞吐、高性能、高可用,功能非常全面。
    • 缺點:開源版功能不如云上商業(yè)版。官方文檔和周邊生態(tài)還不夠成熟。客戶端只支持java。
    • 使用場景:幾乎是全場景。

1.37????????RocketMQ的事務(wù)消息是如何實現(xiàn)的

    1. 生產(chǎn)者訂單系統(tǒng)先發(fā)送一條half消息到Broker,half消息對消費者而言是不可見的
    2. 再創(chuàng)建訂單,根據(jù)創(chuàng)建訂單成功與否,向Broker發(fā)送commit或rollback
    3. 并且生產(chǎn)者訂單系統(tǒng)還可以提供Broker回調(diào)接口,當Broker發(fā)現(xiàn)一段時間half消息沒有收到任何操作命令,則會主動調(diào)此接口來查詢訂單是否創(chuàng)建成功
    4. 一旦half消息commit了,消費者庫存系統(tǒng)就會來消費,如果消費成功,則消息銷毀,分布式事務(wù)成功結(jié)束
    5. 如果消費失敗,則根據(jù)重試策略進行重試,最后還失敗則進入死信隊列,等待進一步處理

1.38????????為什么RocketMQ不使用Zookeeper作為注冊中心呢?

根據(jù)CAP理論,同時最多只能滿足兩個點,而zookeeper滿足的是CP,也就是說zookeeper并不能保證服務(wù)的可用性,zookeeper在進行選舉的時候,整個選舉的時間太長,期間整個集群都處于不可用的狀態(tài),而這對于一個注冊中心來說肯定是不能接受的,作為服務(wù)發(fā)現(xiàn)來說就應(yīng)該是為可用性而設(shè)計。

基于性能的考慮,NameServer本身的實現(xiàn)非常輕量,而且可以通過增加機器的方式水平擴展,增加集群的抗壓能力,而zookeeper的寫是不可擴展的,而zookeeper要解決這個問題只能通過劃分領(lǐng)域,劃分多個zookeeper集群來解決,首先操作起來太復雜,其次這樣還是又違反了CAP中的A的設(shè)計,導致服務(wù)之間是不連通的。

持久化的機制來帶的問題,ZooKeeper 的 ZAB 協(xié)議對每一個寫請求,會在每個 ZooKeeper 節(jié)點上保持寫一個事務(wù)日志,同時再加上定期的將內(nèi)存數(shù)據(jù)鏡像(Snapshot)到磁盤來保證數(shù)據(jù)的一致性和持久性,而對于一個簡單的服務(wù)發(fā)現(xiàn)的場景來說,這其實沒有太大的必要,這個實現(xiàn)方案太重了。而且本身存儲的數(shù)據(jù)應(yīng)該是高度定制化的。

消息發(fā)送應(yīng)該弱依賴注冊中心,而RocketMQ的設(shè)計理念也正是基于此,生產(chǎn)者在第一次發(fā)送消息的時候從NameServer獲取到Broker地址后緩存到本地,如果NameServer整個集群不可用,短時間內(nèi)對于生產(chǎn)者和消費者并不會產(chǎn)生太大影響。

1.39????????RocketMQ的實現(xiàn)原理

RocketMQ由NameServer注冊中心集群、Producer生產(chǎn)者集群、Consumer消費者集群和若干Broker(RocketMQ進程)組成,它的架構(gòu)原理是這樣的:

Broker在啟動的時候去向所有的NameServer注冊,并保持長連接,每30s發(fā)送一次心跳

Producer在發(fā)送消息的時候從NameServer獲取Broker服務(wù)器地址,根據(jù)負載均衡算法選擇一臺服務(wù)器來發(fā)送消息

Conusmer消費消息的時候同樣從NameServer獲取Broker地址,然后主動拉取消息來消費

1.40????????RocketMQ為什么速度快

因為使用了順序存儲、Page Cache和異步刷盤。我們在寫入commitlog的時候是順序?qū)懭氲?,這樣比隨機寫入的性能就會提高很多,寫入commitlog的時候并不是直接寫入磁盤,而是先寫入操作系統(tǒng)的PageCache,最后由操作系統(tǒng)異步將緩存中的數(shù)據(jù)刷到磁盤

1.41????????消息隊列如何保證消息可靠傳輸

消息可靠傳輸代表了兩層意思,既不能多也不能少。

  1. 為了保證消息不多,也就是消息不能重復,也就是生產(chǎn)者不能重復生產(chǎn)消息,或者消費者不能重復消費消息
  2. 首先要確保消息不多發(fā),這個不常出現(xiàn),也比較難控制,因為如果出現(xiàn)了多發(fā),很大的原因是生產(chǎn)者自己的原因,如果要避免出現(xiàn)問題,就需要在消費端做控制
  3. 要避免不重復消費,最保險的機制就是消費者實現(xiàn)冪等性,保證就算重復消費,也不會有問題,通過冪等性,也能解決生產(chǎn)者重復發(fā)送消息的問題
  4. 消息不能少,意思就是消息不能丟失,生產(chǎn)者發(fā)送的消息,消費者一定要能消費到,對于這個問題,就要考慮兩個方面
  5. 生產(chǎn)者發(fā)送消息時,要確認broker確實收到并持久化了這條消息,比如RabbitMQ的confirm機制,Kafka的ack機制都可以保證生產(chǎn)者能正確的將消息發(fā)送給broker
  6. broker要等待消費者真正確認消費到了消息時才刪除掉消息,這里通常就是消費端ack機制,消費者接收到一條消息后,如果確認沒問題了,就可以給broker發(fā)送一個ack,broker接收到ack后才會刪除消息

1.42????????消息隊列有哪些作用

  1. 解耦:使用消息隊列來作為兩個系統(tǒng)之間的通訊方式,兩個系統(tǒng)不需要相互依賴了
  2. 異步:系統(tǒng)A給消息隊列發(fā)送完消息之后,就可以繼續(xù)做其他事情了
  3. 流量削峰:如果使用消息隊列的方式來調(diào)用某個系統(tǒng),那么消息將在隊列中排隊,由消費者自己控制消費速度

1.43????????死信隊列是什么?延時隊列是什么?

  1. 死信隊列也是一個消息隊列,它是用來存放那些沒有成功消費的消息的,通??梢杂脕碜鳛橄⒅卦?/span>
  2. 延時隊列就是用來存放需要在指定時間被處理的元素的隊列,通??梢杂脕硖幚硪恍┚哂羞^期性操作的業(yè)務(wù),比如十分鐘內(nèi)未支付則取消訂單

1.44????????如何保證消息的高效讀寫?

零拷貝: kafka和RocketMQ都是通過零拷貝技術(shù)來優(yōu)化文件讀寫。

傳統(tǒng)文件復制方式: 需要對文件在內(nèi)存中進行四次拷貝。

零拷貝: 有兩種方式, mmap和transfile,Java當中對零拷貝進行了封裝, Mmap方式通過MappedByteBuffer對象進行操作,而transfile通過FileChannel來進行操作。Mmap 適合比較小的文件,通常文件大小不要超過1.5G ~2G 之間。Transfile沒有文件大小限制。RocketMQ當中使用Mmap方式來對他的文件進行讀寫。

在kafka當中,他的index日志文件也是通過mmap的方式來讀寫的。在其他日志文件當中,并沒有使用零拷貝的方式。Kafka使用transfile方式將硬盤數(shù)據(jù)加載到網(wǎng)卡。

1.45????????epoll和poll的區(qū)別

  1. select模型,使用的是數(shù)組來存儲Socket連接文件描述符,容量是固定的,需要通過輪詢來判斷是否發(fā)生了IO事件
  2. poll模型,使用的是鏈表來存儲Socket連接文件描述符,容量是不固定的,同樣需要通過輪詢來判斷是否發(fā)生了IO事件
  3. epoll模型,epoll和poll是完全不同的,epoll是一種事件通知模型,當發(fā)生了IO事件時,應(yīng)用程序才進行IO操作,不需要像poll模型那樣主動去輪詢

三? ? ? ? 網(wǎng)絡(luò)

1.46????????TCP的三次握手和四次揮手

TCP協(xié)議是7層網(wǎng)絡(luò)協(xié)議中的傳輸層協(xié)議,負責數(shù)據(jù)的可靠傳輸。

在建立TCP連接時,需要通過三次握手來建立,過程是:

  1. 客戶端向服務(wù)端發(fā)送一個SYN
  2. 服務(wù)端接收到SYN后,給客戶端發(fā)送一個SYN_ACK
  3. 客戶端接收到SYN_ACK后,再給服務(wù)端發(fā)送一個ACK

在斷開TCP連接時,需要通過四次揮手來斷開,過程是:

  1. 客戶端向服務(wù)端發(fā)送FIN
  2. 服務(wù)端接收FIN后,向客戶端發(fā)送ACK,表示我接收到了斷開連接的請求,客戶端你可以不發(fā)數(shù)據(jù)了,不過服務(wù)端這邊可能還有數(shù)據(jù)正在處理
  3. 服務(wù)端處理完所有數(shù)據(jù)后,向客戶端發(fā)送FIN,表示服務(wù)端現(xiàn)在可以斷開連接
  4. 客戶端收到服務(wù)端的FIN,向服務(wù)端發(fā)送ACK,表示客戶端也會斷開連接了

1.47????????瀏覽器發(fā)出一個請求到收到響應(yīng)經(jīng)歷了哪些步驟?

  1. 瀏覽器解析用戶輸入的URL,生成一個HTTP格式的請求
  2. 先根據(jù)URL域名從本地hosts文件查找是否有映射IP,如果沒有就將域名發(fā)送給電腦所配置的DNS進行域名解析,得到IP地址
  3. 瀏覽器通過操作系統(tǒng)將請求通過四層網(wǎng)絡(luò)協(xié)議發(fā)送出去
  4. 途中可能會經(jīng)過各種路由器、交換機,最終到達服務(wù)器
  5. 服務(wù)器收到請求后,根據(jù)請求所指定的端口,將請求傳遞給綁定了該端口的應(yīng)用程序,比如8080被tomcat占用了
  6. tomcat接收到請求數(shù)據(jù)后,按照http協(xié)議的格式進行解析,解析得到所要訪問的servlet
  7. 然后servlet來處理這個請求,如果是SpringMVC中的DispatcherServlet,那么則會找到對應(yīng)的Controller中的方法,并執(zhí)行該方法得到結(jié)果
  8. Tomcat得到響應(yīng)結(jié)果后封裝成HTTP響應(yīng)的格式,并再次通過網(wǎng)絡(luò)發(fā)送給瀏覽器所在的服務(wù)器
  9. 瀏覽器所在的服務(wù)器拿到結(jié)果后再傳遞給瀏覽器,瀏覽器則負責解析并渲染

1.48????????跨域請求是什么?有什么問題?怎么解決?

跨域是指瀏覽器在發(fā)起網(wǎng)絡(luò)請求時,會檢查該請求所對應(yīng)的協(xié)議、域名、端口和當前網(wǎng)頁是否一致,如果不一致則瀏覽器會進行限制,比如在www.baidu.com的某個網(wǎng)頁中,如果使用ajax去訪問www.jd.com是不行的,但是如果是img、iframe、script等標簽的src屬性去訪問則是可以的,之所以瀏覽器要做這層限制,是為了用戶信息安全。但是如果開發(fā)者想要繞過這層限制也是可以的:

  1. response添加header,比如resp.setHeader("Access-Control-Allow-Origin", "*");表示可以訪問所有網(wǎng)站,不受是否同源的限制
  2. jsonp的方式,該技術(shù)底層就是基于script標簽來實現(xiàn)的,因為script標簽是可以跨域的
  3. 后臺自己控制,先訪問同域名下的接口,然后在接口中再去使用HTTPClient等工具去調(diào)用目標接口
  4. 網(wǎng)關(guān),和第三種方式類似,都是交給后臺服務(wù)來進行跨域訪問

1.49????????零拷貝是什么

零拷貝指的是,應(yīng)用程序在需要把內(nèi)核中的一塊區(qū)域數(shù)據(jù)轉(zhuǎn)移到另外一塊內(nèi)核區(qū)域去時,不需要經(jīng)過先復制到用戶空間,再轉(zhuǎn)移到目標內(nèi)核區(qū)域去了,而直接實現(xiàn)轉(zhuǎn)移。

cap 選舉,分布式,zookeeper,dubbo

1.50????????MySQL里有2000w數(shù)據(jù)Redis中只存20w的數(shù)據(jù),如何保證 redis 中的數(shù)據(jù)都是熱點數(shù)據(jù)?(北冥)

這道題主要考察的是Redis的數(shù)據(jù)淘汰策略(這里有個誤區(qū),很多人容易混淆把數(shù)據(jù)淘汰策略當做數(shù)據(jù)過期策略),在Redis 4.0之后是為我們提供了8種淘汰策略,4.0之前則是提供的6種,主要是新增了LFU算法。其實說說是有8種,但是真正意義上是5種,針對random、lru、lfu是提供了兩種不同數(shù)據(jù)范圍的策略,一種是針對設(shè)置了過期時間的,一種是沒有設(shè)置過期時間的。具體的五種策略分別為:

  1. noeviction 選擇這種策略則代表不進行數(shù)據(jù)淘汰,同時它也是redis中默認的淘汰策略,當緩存寫滿時redis就不再提供寫服務(wù)了,寫請求則直接返回失敗。
  2. random 隨機策略這塊則是分為兩種,一種是volatile,這種是設(shè)置了過期時間得數(shù)據(jù)集,而另外一種是allkeys,這種是包含了所有的數(shù)據(jù),當我們緩存滿了的時候,選用這種策略就會在我們的數(shù)據(jù)集中進行隨機刪除。
  3. volatile-ttl 這種策略是針對設(shè)置了過期時間的數(shù)據(jù),并且按照過期時間的先后順序進行刪除,越早過期的越先被刪除
  4. lru 這里的lru策略和我們上面random策略一樣也是提供了兩種數(shù)據(jù)集進行處理,LRU算法全程為(最近最少使用)簡單一句話來概括就是“如果數(shù)據(jù)最近被訪問過,那么將來被訪問的幾率也就越高”。這種算法其實已經(jīng)比較符合我們的實際業(yè)務(wù)需求了,但是還是存在一些缺陷。
  5. lfu 最后一種策略就是我們的LFU算法,它是在我么LRU算法基礎(chǔ)上增加了請求數(shù)統(tǒng)計,這樣能夠更加精準的代表我們的熱點數(shù)據(jù)。

我們再回看我們的這個問題,我們能很清楚的知道,我們需要的策略是LFU算法。選擇volatile還是allkeys就要根據(jù)具體的業(yè)務(wù)需求了。

?1.51????????高并發(fā)下我們?nèi)绾稳ケWC接口的冪等性?(北冥)

首先普及下冪等的概念

在編程中一個冪等操作的特點是其任意多次執(zhí)行所產(chǎn)生的影響均與一次執(zhí)行的影響相同。冪等函數(shù),或冪等方法,是指可以使用相同參數(shù)重復執(zhí)行,并能獲得相同結(jié)果的函數(shù)

那么在我們的實際業(yè)務(wù)場景中冪等是一個非常高頻的場景,比如:

  • 電商場景中用戶因網(wǎng)絡(luò)問題多次點擊導致重復下單問題
  • MQ消息隊列的重復消費
  • RPC中的超時重試機制
  • 等等

那么我們有那些方案可以解決我們的冪等性問題呢?

  • 數(shù)據(jù)庫唯一主鍵實現(xiàn)冪等性
    • 其實現(xiàn)方式是使用分布式ID充當主鍵,不使用MySQL中的自增主鍵
  • 樂觀鎖實現(xiàn)冪等性
    • 在表中增加版本號標識,只有版本號標識一直才更新成功
  • 分布式鎖
    • 簡單來說就是分布式的排他鎖,但是我們可以控制鎖的粒度以提高程序的執(zhí)行性能
  • 獲取token

服務(wù)端提供獲取 Token 的接口,請求前客戶端調(diào)用接口獲取 Token

然后將該串存入 Redis 數(shù)據(jù)庫中,以該 Token 作為 Redis 的鍵(注意設(shè)置過期時間)。

將 Token 返回到客戶端,在執(zhí)行業(yè)務(wù)請求帶上該 Token

服務(wù)端接收到請求后根據(jù) Token 到 Redis 中查找該 key 是否存在(注意原子性),

如果存在就將該 key 刪除,然后正常執(zhí)行業(yè)務(wù)邏輯。如果不存在就拋異常,返回重復提交的錯誤信息。

1.52????????Redis如何保證與數(shù)據(jù)庫的雙寫一致性(北冥)

我們來分析一下這道面試題,這道題主要是偏實際應(yīng)用的

緩存可以提升性能,減輕數(shù)據(jù)庫壓力,在獲取這部分好處的同時,它卻帶來了一些新的問題,緩存和數(shù)據(jù)庫之間的數(shù)據(jù)一致性問題。

想必大家在工作中只要用了咱們緩存勢必就會遇到過此類問題,那這道題該如何回答呢?

首先我們來看看一致性:

  • 強一致性:任何一次讀都能讀到某個數(shù)據(jù)的最近一次寫的數(shù)據(jù)。
  • 弱一致性:數(shù)據(jù)更新后,如果能容忍后續(xù)的訪問只能訪問到部分或者全部訪問不到,則是弱一致性。

解決雙寫一致性方案:

  • 延遲雙刪
    • 延遲雙刪策略是分布式系統(tǒng)中數(shù)據(jù)庫存儲和緩存數(shù)據(jù)保持一致性的常用策略,但它不是強一致。
    • 實現(xiàn)思路:也是非常簡單的,先刪除緩存然后更新DB在最后延遲 N 秒去再去執(zhí)行一次緩存刪除
    • 弊端:小概率會出現(xiàn)不一致情況、耦合程度高
  • 通過MQ進行重試刪除
    • 更新完DB之后進行刪除,如果刪除失敗則向MQ發(fā)送一條消息,然后消費者不斷進行刪除嘗試。
  • binlog異步刪除
    • 實現(xiàn)思路:低耦合的解決方案是使用canal。canal偽裝成mysql的從機,監(jiān)聽主機mysql的二進制文件,當數(shù)據(jù)發(fā)生變化時發(fā)送給MQ。最終消費進行刪除

1.53????????談?wù)劸彺娲┩?、擊穿、雪崩的區(qū)別,又如何去解決?(北冥)

面試題分析

這道題主要考察的是求職者是否具有高并發(fā)思維,它也是在面試中一道高頻的考點

緩存穿透

緩存穿透代表的意思是在我們的緩存中沒有找到緩存信息,那么我們在高并發(fā)場景下就會面臨所有的請求都會直接打到DB,緩存則失去了它原本的意義,并且極有可能導致數(shù)據(jù)庫壓力過大而造成服務(wù)不可用。

  • 緩存空結(jié)果信息
  • 布隆過濾器(不存在的一定不存在,存在的可能不存在,通過bitmap實現(xiàn),想深入布隆過濾器可以專門去看看這部分專題內(nèi)容)
  • 過濾常見非法參數(shù),攔截大部分無效請求()
緩存擊穿

緩存擊穿代表的意思是我們數(shù)據(jù)庫中存在數(shù)據(jù),但是緩存中不存在數(shù)據(jù).這種場景一般是在緩存失效時發(fā)生的. 在高并發(fā)的場景下極有可能瞬間打垮數(shù)據(jù)庫.

  • 我們可以考慮面對請求量大的熱點接口直接將緩存設(shè)置永不過期.
  • 當然我們也可能碰到一些特殊場景不能設(shè)置永久緩存,那么我們可以在db為空時設(shè)置互斥鎖,當查詢完db更新至緩存時再釋放鎖
緩存雪崩

緩存雪崩代表是意思是我們在某一個時間段,碰到大量熱點緩存數(shù)據(jù)過期導致大量請求直接打垮數(shù)據(jù)庫

  • 我們可以考慮面對請求量大的熱點接口直接將緩存設(shè)置永不過期.
  • 緩存過期時間可以設(shè)置一個隨機的波動值,防止大量數(shù)據(jù)在同一時間過期

1.54????????Redis 事務(wù)支持 ACID 么?(北冥)

原子性(Atomicity):一個事務(wù)的多個操作必須完成,或者都不完成。

一致性(Consistency):事務(wù)執(zhí)行結(jié)束后,數(shù)據(jù)庫的完整性約束沒有被破壞,事務(wù)執(zhí)行的前后順序都是合法數(shù)據(jù)狀態(tài)。

隔離性(Isolation):事務(wù)內(nèi)部的操作與其他事務(wù)是隔離的,并發(fā)執(zhí)行的各個事務(wù)之間不能互相干擾。

持久性(Durability):事務(wù)一旦提交,所有的修改將永久的保存到數(shù)據(jù)庫中,即使系統(tǒng)崩潰重啟后數(shù)據(jù)也不會丟失。

redis事務(wù)功能是通過MULTI、EXEC、DISCARD和WATCH 四個原語實現(xiàn)的

Redis會將一個事務(wù)中的所有命令序列化,然后按順序執(zhí)行。

單獨的隔離操作

  • 事務(wù)中的所有命令都會序列化、按順序地執(zhí)行。事務(wù)在執(zhí)行的過程中,不會被其他客戶端發(fā)送來的命令請求所打斷。

沒有隔離級別的概念

  • 隊列中的命令沒有提交之前都不會實際被執(zhí)行,因為事務(wù)提交前任何指令都不會被實際執(zhí)行

不保證原子性

  • 事務(wù)中如果有一條命令執(zhí)行失敗,其后的命令仍然會被執(zhí)行,沒有回滾

注:redis的discard只是結(jié)束本次事務(wù),正確命令造成的影響仍然存在.

1)MULTI命令用于開啟一個事務(wù),它總是返回OK。MULTI執(zhí)行之后,客戶端可以繼續(xù)向服務(wù)器發(fā)送任意多條命令,這些命令不會立即被執(zhí)行,而是被放到一個隊列中,當EXEC命令被調(diào)用時,所有隊列中的命令才會被執(zhí)行。

2)EXEC:執(zhí)行所有事務(wù)塊內(nèi)的命令。返回事務(wù)塊內(nèi)所有命令的返回值,按命令執(zhí)行的先后順序排列。當操作被打斷時,返回空值 nil 。

3)通過調(diào)用DISCARD,客戶端可以清空事務(wù)隊列,并放棄執(zhí)行事務(wù), 并且客戶端會從事務(wù)狀態(tài)中退出。

4)WATCH 命令可以為 Redis 事務(wù)提供 check-and-set (CAS)行為??梢员O(jiān)控一個或多個鍵,一旦其中有一個鍵被修改(或刪除),之后的事務(wù)就不會執(zhí)行,監(jiān)控一直持續(xù)到EXEC命令。

1.55????????Redis持久化有那些方案,線上又是如何配置的呢?(北冥)

Redis為我們提供了兩種持久化方案,一種是RDB另外一種是AOF

RDB快照

RDB (Redis DataBase) 把當前進程數(shù)據(jù)生成快照保存到磁盤上的過程,由于是某一時刻的快照,那么快照中的值要早于或者等于內(nèi)存中的值。

優(yōu)點

  1. 基于某個時間節(jié)點的快照,壓縮后文件體積小
  2. 加載RDB文件恢復快

缺點

  1. 實時性不夠
  2. 通過bgsave進行備份時,需要fork一個子線程,頻繁執(zhí)行性能成本高
AOF

Redis是“寫后”日志,Redis先執(zhí)行命令,把數(shù)據(jù)寫入內(nèi)存,然后才記錄日志。日志里記錄的是Redis收到的每一條命令,這些命令是以文本形式保存。

優(yōu)點

  1. 根據(jù)策略的不同AOF的方式能做到基本不丟失數(shù)據(jù)

缺點

  1. 文件體積大,AOF的文件體積要大于RDB
  2. 在大數(shù)據(jù)量情況下恢復速度慢

1.56????????private修飾的方法可以通過反射訪問,那么private的意義是什么?(北冥)

在Java當中,如果為了我們不想讓別人訪問某些屬性、方法,我們通常的做法是使用private關(guān)鍵字進行修飾。但是Java語言在設(shè)計時卻允許通過反射來進行訪問,只需要關(guān)掉訪問檢查就可以了。

其實不盡然,本身private修飾符是基于OOP思想下封裝概念的一種體現(xiàn),對于使用者而言是一種約束,并不是一種安全機制。就好比說,你在道路上行駛,導航時不時提醒你限速,這是道路交通法的規(guī)定,但是救護車碰上情況是不是也會超速對吧,這個就是這兩者的差異。

你在用spring的IoC的時候,你知道你要“注入”,不管它是不是private的,都能夠注入進去對吧。

如果你按照遵守這套規(guī)則,開發(fā)者在不考慮bug的情況下可以保證不出問題,否則就很有可能在你意想不到的地方帶來災(zāi)難性的后果。文章來源地址http://www.zghlxwxcb.cn/news/detail-849034.html

到了這里,關(guān)于分布式事務(wù),zookeeper,dubbo,rocketmq的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • SpringBoot整合Dubbo和Zookeeper分布式服務(wù)框架使用的入門項目實例

    SpringBoot整合Dubbo和Zookeeper分布式服務(wù)框架使用的入門項目實例

    Dubbo是一個 分布式服務(wù)框架 ,致力于提供高性能和透明化的RPC遠程服務(wù)調(diào)用方案,以及SOA服務(wù)治理方案。簡單的說,dubbo就是個服務(wù)框架,如果沒有分布式的需求,其實是不需要用的,只有在分布式的時候,才有dubbo這樣的分布式服務(wù)框架的需求。其本質(zhì)上是個遠程服務(wù)調(diào)用

    2024年01月21日
    瀏覽(57)
  • 分布式RPC框架Dubbo詳解

    分布式RPC框架Dubbo詳解

    目錄 ? 1.架構(gòu)演進 1.1 單體架構(gòu) 1.2? 垂直架構(gòu) 1.3 分布式架構(gòu) 1.4 SOA架構(gòu) 1.5 微服務(wù)架構(gòu) 2.RPC框架 2.1 RPC基本概念介紹 2.1.1 RPC協(xié)議 2.1.2 RPC框架 2.1.3 RPC與HTTP、TCP/ UDP、Socket的區(qū)別 2.1.4 RPC的運行流程 ?2.1.5 為什么需要RPC 2.2 Dubbo? 2.2.1 Dubbo 概述 2.2.2 Dubbo實戰(zhàn) ? 架構(gòu)演進如下圖: 這

    2024年02月07日
    瀏覽(38)
  • 分布式:一文吃透分布式事務(wù)和seata事務(wù)

    分布式:一文吃透分布式事務(wù)和seata事務(wù)

    什么是事務(wù) 事務(wù)是并發(fā)控制的單位,是用戶定義的一個操作序列。 事務(wù)特性 原子性(Atomicity): 事務(wù)是數(shù)據(jù)庫的邏輯工作單位,事務(wù)中包括的諸操作要么全做,要么全不做。 一致性(Consistency): 事務(wù)執(zhí)行的結(jié)果必須是使數(shù)據(jù)庫從一個一致性狀態(tài)變到另一個一致性狀態(tài)。一致性

    2024年02月07日
    瀏覽(21)
  • 基于Dubbo分布式網(wǎng)上售票系統(tǒng)

    基于Dubbo分布式網(wǎng)上售票系統(tǒng)

    民航售票是一個高度依賴信息業(yè)的行業(yè)。但在機票銷售的管理和規(guī)范這方面上存在著很多各種各樣的問題。例如訂票是客運行業(yè)中的一個最基本的業(yè)務(wù),表面上看,它只是機票站業(yè)務(wù)的一個簡單的部分,但是它涉及到管理與客戶服務(wù)等多方面,關(guān)系到民航公司能否正常運作。

    2024年02月16日
    瀏覽(24)
  • 【分布式事務(wù)】Seata 開源的分布式事務(wù)解決方案

    【分布式事務(wù)】Seata 開源的分布式事務(wù)解決方案

    Seata 是一款開源的分布式事務(wù)解決方案,致力于提供高性能和簡單易用的分布式事務(wù)服務(wù)。Seata 將為用戶提供了 AT、TCC、SAGA 和 XA 事務(wù)模式,為用戶打造一站式的分布式解決方案。 阿里巴巴作為國內(nèi)最早一批進行應(yīng)用分布式(微服務(wù)化)改造的企業(yè),很早就遇到微服務(wù)架構(gòu)下

    2024年02月02日
    瀏覽(18)
  • 【分布式】分布式事務(wù):2PC

    【分布式】分布式事務(wù):2PC

    分布式事務(wù)的問題可以分為兩部分: 并發(fā)控制 concurrency control 原子提交 atomic commit 分布式事務(wù)問題的產(chǎn)生場景:一份數(shù)據(jù)被分片存在多臺服務(wù)器上,那么每次事務(wù)處理都涉及到了多臺機器。 可序列化(并發(fā)控制): 定義了事務(wù)執(zhí)行的正確性 真正地并行執(zhí)行事務(wù),獲得真正的

    2024年02月09日
    瀏覽(19)
  • Dubbo——微服務(wù)框架(單體式->分布式->微服務(wù))

    Dubbo——微服務(wù)框架(單體式->分布式->微服務(wù))

    Dubbo是阿里巴巴開源的基于Java的高性能RPC(一種遠程調(diào)用)分布式服務(wù)框架,致力于提供高性能和透明化的RPC遠程服務(wù)調(diào)用方案,以及SOA服務(wù)治理方案,它提供了三大核心能力:面向接口的遠程方法調(diào)用,智能容錯和負載均衡,以及服務(wù)自動注冊和發(fā)現(xiàn)。; 每天為2千多個服

    2024年02月05日
    瀏覽(31)
  • Redis分布式鎖和分布式事務(wù)

    Redis分布式鎖和分布式事務(wù) 一、Redis分布式鎖 1.1 watch和事務(wù)實現(xiàn)分布式鎖 原理是通過watch來觀察一個變量,一個線程在操作的時候,其他線程會操作失敗,相當于樂觀鎖。 1.2 setnx實現(xiàn)分布式鎖 原理是通過setnx設(shè)置一個變量,設(shè)置成功的線程搶到鎖,執(zhí)行相關(guān)的業(yè)務(wù),執(zhí)行完畢

    2024年02月09日
    瀏覽(25)
  • 基于Dubbo分布式倉庫管理系統(tǒng)設(shè)計與實現(xiàn)

    現(xiàn)如今,互聯(lián)網(wǎng)的發(fā)展速度是人們有目共睹的,它的迅速發(fā)展從源頭上改變了全世界對于管理的方式以及管理方法,從上世紀九十年代以來,我國各種單位和許多部門就在思考能否依靠互聯(lián)網(wǎng)來對信息管理進行優(yōu)化。雖然在以前,想讓倉庫管理和互聯(lián)網(wǎng)相互結(jié)合存在許多方面

    2024年02月11日
    瀏覽(24)
  • 基于Dubbo分布式學校信息管理系統(tǒng)設(shè)計與實現(xiàn)

    基于Dubbo分布式學校信息管理系統(tǒng)設(shè)計與實現(xiàn)

    隨著時代的發(fā)展與進步,計算機網(wǎng)絡(luò)也隨之日益完善,漸漸覆蓋了我們生活的各個方面。在信息化和數(shù)字化的時代背景下,使用計算機管理學校信息來提升教育工作的質(zhì)量和效率,是大勢所趨,所以近年來,隨著網(wǎng)絡(luò)技術(shù)的不斷發(fā)展,使用信息管理系統(tǒng)的學校越來越多,學校

    2024年02月11日
    瀏覽(23)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包