同是ZooKeeper煤率,你和架構(gòu)師的理解差在哪里?

前言

提到ZooKeeper乏冀,相信大家都不會陌生蝶糯。DubboKafka,Hadoop等等項(xiàng)目里都能看到它的影子辆沦。但是你真的了解 ZooKeeper 嗎昼捍?如果面試官讓你給他講講 ZooKeeper 是個(gè)什么東西,你能回答到什么地步呢肢扯?

而且妒茬,同樣是ZooKeeper,一線架構(gòu)師和你的理解又有哪些不同呢蔚晨?

  • 如何從一個(gè)問題及思考方式了解架構(gòu)的本質(zhì)乍钻?
  • 如何剖析ZooKeeper為什么這么設(shè)計(jì)?
  • ZooKeeper到底能干嘛铭腕?

如果你已經(jīng)工作了2-3年银择,有沒有思考過上述3個(gè)問題?

——如果有累舷,你的答案會是浩考?
——如果沒有,為什么被盈?

下面析孽,我主要介紹一下ZooKeeper是什么以及ZooKeeper的作用,前面兩個(gè)問題只怎,我會在文末給出答案绿淋。

一、ZooKeeper是什么

ZooKeeper 是一個(gè)分布式的尝盼,開放源碼的分布式應(yīng)用程序協(xié)調(diào)服務(wù)吞滞,是Google的Chubby一個(gè)開源的實(shí)現(xiàn),是Hadoop和Hbase的重要組件盾沫。它是一個(gè)為分布式應(yīng)用提供一致性服務(wù)的軟件裁赠,提供的功能包括:配置維護(hù)、域名服務(wù)赴精、分布式同步佩捞、組服務(wù)等。

官網(wǎng):http://zookeeper.apache.org/
源碼:https://github.com/apache/zookeeper

ZooKeeper翻譯成中文是“動物園管理員”蕾哟,至于為什么這么翻譯一忱,感興趣的話可以去看看《從Paxos到Zookeeper 》 莲蜘,本文中很多的名詞介紹也來自本書。

三帘营、ZooKeeper的特性

  • 順序一致性票渠,從同一個(gè)客戶端發(fā)起的事務(wù)請求,最終將會嚴(yán)格地按照其發(fā)起順序被應(yīng)用到Zookeeper中去芬迄。

  • 原子性问顷,所有事務(wù)請求的處理結(jié)果在整個(gè)集群中所有機(jī)器上的應(yīng)用情況是一致的,即整個(gè)集群要么都成功應(yīng)用了某個(gè)事務(wù)禀梳,要么都沒有應(yīng)用杜窄。

  • 單一視圖,無論客戶端連接的是哪個(gè) Zookeeper 服務(wù)器算途,其看到的服務(wù)端數(shù)據(jù)模型都是一致的塞耕。

  • 可靠性,一旦服務(wù)端成功地應(yīng)用了一個(gè)事務(wù)嘴瓤,并完成對客戶端的響應(yīng)荷科,那么該事務(wù)所引起的服務(wù)端狀態(tài)變更將會一直被保留,除非有另一個(gè)事務(wù)對其進(jìn)行了變更纱注。

  • 實(shí)時(shí)性,Zookeeper 保證在一定的時(shí)間段內(nèi)胆胰,客戶端最終一定能夠從服務(wù)端上讀取到最新的數(shù)據(jù)狀態(tài)狞贱。

四、ZooKeeper的設(shè)計(jì)目標(biāo)

  • 簡單的數(shù)據(jù)結(jié)構(gòu)
    Zookeeper 使得分布式程序能夠通過一個(gè)共享的樹形結(jié)構(gòu)的名字空間來進(jìn)行相互協(xié)調(diào)蜀涨,即Zookeeper 服務(wù)器內(nèi)存中的數(shù)據(jù)模型由一系列被稱為ZNode的數(shù)據(jù)節(jié)點(diǎn)組成瞎嬉,Zookeeper 將全量的數(shù)據(jù)存儲在內(nèi)存中,以此來提高服務(wù)器吞吐厚柳、減少延遲的目的氧枣。

  • 可以構(gòu)建集群
    Zookeeper 集群通常由一組機(jī)器構(gòu)成,組成 Zookeeper 集群的而每臺機(jī)器都會在內(nèi)存中維護(hù)當(dāng)前服務(wù)器狀態(tài)别垮,并且每臺機(jī)器之間都相互通信便监。

  • 順序訪問
    對于來自客戶端的每個(gè)更新請求,Zookeeper 都會分配一個(gè)全局唯一的遞增編號碳想,這個(gè)編號反映了所有事務(wù)操作的先后順序烧董。

  • 高性能
    Zookeeper 和Redis一樣全量數(shù)據(jù)存儲在內(nèi)存中,100%讀請求壓測QPS 12-13W胧奔。

五逊移、關(guān)于 ZooKeeper 的一些重要概念

5.1 Zookeeper 集群:

Zookeeper 是一個(gè)由多個(gè) server 組成的集群,一個(gè) leader,多個(gè) follower龙填。(這個(gè)不同于我們常見的Master/Slave模式)leader 為客戶端服務(wù)器提供讀寫服務(wù)胳泉,除了leader外其他的機(jī)器只能提供讀服務(wù)拐叉。
每個(gè) server 保存一份數(shù)據(jù)副本全數(shù)據(jù)一致,分布式讀 follower扇商,寫由 leader 實(shí)施更新請求轉(zhuǎn)發(fā)凤瘦,由 leader 實(shí)施更新請求順序進(jìn)行,來自同一個(gè) client 的更新請求按其發(fā)送順序依次執(zhí)行數(shù)據(jù)更新原子性钳吟,一次數(shù)據(jù)更新要么成功廷粒,要么失敗。全局唯一數(shù)據(jù)視圖红且,client 無論連接到哪個(gè) server坝茎,數(shù)據(jù)視圖都是一致的實(shí)時(shí)性,在一定事件范圍內(nèi)暇番,client 能讀到最新數(shù)據(jù)嗤放。


image

5.2 集群角色

Leader:是整個(gè) Zookeeper 集群工作機(jī)制中的核心 。Leader 作為整個(gè) ZooKeeper 集群的主節(jié)點(diǎn)壁酬,負(fù)責(zé)響應(yīng)所有對 ZooKeeper 狀態(tài)變更的請求次酌。
主要工作:

  • 事務(wù)請求的唯一調(diào)度和處理,保障集群處理事務(wù)的順序性舆乔。
  • 集群內(nèi)各服務(wù)器的調(diào)度者岳服。

Leader 選舉是 Zookeeper 最重要的技術(shù)之一,也是保障分布式數(shù)據(jù)一致性的關(guān)鍵所在希俩。我們以三臺機(jī)器為例吊宋,在服務(wù)器集群初始化階段,當(dāng)有一臺服務(wù)器Server1啟動時(shí)候是無法完成選舉的颜武,當(dāng)?shù)诙_機(jī)器 Server2 啟動后兩臺機(jī)器能互相通信璃搜,每臺機(jī)器都試圖找到一個(gè)leader,于是便進(jìn)入了 leader 選舉流程.

  1. 每個(gè) server 發(fā)出一個(gè)投票
    投票的最基本元素是(SID-服務(wù)器id,ZXID-事物id)
  2. 接受來自各個(gè)服務(wù)器的投票
  3. 處理投票
    優(yōu)先檢查 ZXID(數(shù)據(jù)越新ZXID越大),ZXID比較大的作為leader鳞上,ZXID一樣的情況下比較SID
  4. 統(tǒng)計(jì)投票
    這里有個(gè)過半的概念这吻,大于集群機(jī)器數(shù)量的一半,即大于或等于(n/2+1),我們這里的由三臺篙议,大于等于2即為達(dá)到“過半”的要求唾糯。
    這里也有引申到為什么 Zookeeper 集群推薦是單數(shù)。
集群數(shù)量 至少正常運(yùn)行數(shù)量 允許掛掉的數(shù)量
2 2的半數(shù)為1鬼贱,半數(shù)以上最少為2 0
3 3的半數(shù)為1.5趾断,半數(shù)以上最少為2 1
4 4的半數(shù)為2,半數(shù)以上最少為3 1
5 5的半數(shù)為2.5吩愧,半數(shù)以上最少為3 2
6 6的半數(shù)為3芋酌,半數(shù)以上最少為4 2

通過以上可以發(fā)現(xiàn),3臺服務(wù)器和4臺服務(wù)器都最多允許1臺服務(wù)器掛掉雁佳,5臺服務(wù)器和6臺服務(wù)器都最多允許2臺服務(wù)器掛掉,明顯4臺服務(wù)器成本高于3臺服務(wù)器成本脐帝,6臺服務(wù)器成本高于5服務(wù)器成本同云。這是由于半數(shù)以上投票通過決定的。

  1. 改變服務(wù)器狀態(tài)
    一旦確定了 leader堵腹,服務(wù)器就會更改自己的狀態(tài)炸站,且一半不會再發(fā)生變化,比如新機(jī)器加入集群疚顷、非 leader 掛掉一臺旱易。

Follower :是 Zookeeper 集群狀態(tài)的跟隨者。他的邏輯就比較簡單腿堤。除了響應(yīng)本服務(wù)器上的讀請求外阀坏,follower 還要處理leader 的提議,并在 leader 提交該提議時(shí)在本地也進(jìn)行提交笆檀。另外需要注意的是忌堂,leader 和 follower 構(gòu)成ZooKeeper 集群的法定人數(shù),也就是說酗洒,只有他們才參與新 leader的選舉士修、響應(yīng) leader 的提議。

Observer :服務(wù)器充當(dāng)一個(gè)觀察者的角色樱衷。如果 ZooKeeper 集群的讀取負(fù)載很高棋嘲,或者客戶端多到跨機(jī)房,可以設(shè)置一些 observer 服務(wù)器矩桂,以提高讀取的吞吐量沸移。Observer 和 Follower 比較相似,只有一些小區(qū)別:首先 observer 不屬于法定人數(shù)耍鬓,即不參加選舉也不響應(yīng)提議,也不參與寫操作的“過半寫成功”策略流妻;其次是 observer 不需要將事務(wù)持久化到磁盤牲蜀,一旦 observer 被重啟,需要從 leader 重新同步整個(gè)名字空間绅这。

5.3會話(Session)

Session 指的是 ZooKeeper 服務(wù)器與客戶端會話涣达。在 ZooKeeper 中,一個(gè)客戶端連接是指客戶端和服務(wù)器之間的一個(gè) TCP 長連接证薇《忍Γ客戶端啟動的時(shí)候,首先會與服務(wù)器建立一個(gè) TCP 連接浑度,從第一次連接建立開始寇窑,客戶端會話的生命周期也開始了。通過這個(gè)連接箩张,客戶端能夠通過心跳檢測與服務(wù)器保持有效的會話甩骏,也能夠向Zookeeper 服務(wù)器發(fā)送請求并接受響應(yīng)窗市,同時(shí)還能夠通過該連接接收來自服務(wù)器的Watch事件通知。 Session 的 sessionTimeout 值用來設(shè)置一個(gè)客戶端會話的超時(shí)時(shí)間饮笛。當(dāng)由于服務(wù)器壓力太大咨察、網(wǎng)絡(luò)故障或是客戶端主動斷開連接等各種原因?qū)е驴蛻舳诉B接斷開時(shí),只要在sessionTimeout規(guī)定的時(shí)間內(nèi)能夠重新連接上集群中任意一臺服務(wù)器福青,那么之前創(chuàng)建的會話仍然有效摄狱。在為客戶端創(chuàng)建會話之前,服務(wù)端首先會為每個(gè)客戶端都分配一個(gè)sessionID无午。由于 sessionID 是 Zookeeper 會話的一個(gè)重要標(biāo)識媒役,許多與會話相關(guān)的運(yùn)行機(jī)制都是基于這個(gè) sessionID 的,因此指厌,無論是哪臺服務(wù)器為客戶端分配的 sessionID刊愚,都務(wù)必保證全局唯一。

5.3.1 會話(Session)

在Zookeeper客戶端與服務(wù)端成功完成連接創(chuàng)建后踩验,就創(chuàng)建了一個(gè)會話鸥诽,Zookeeper會話在整個(gè)運(yùn)行期間的生命周期中,會在不同的會話狀態(tài)中之間進(jìn)行切換箕憾,這些狀態(tài)可以分為CONNECTING牡借、CONNECTED、RECONNECTING袭异、RECONNECTED钠龙、CLOSE等。

一旦客戶端開始創(chuàng)建Zookeeper對象御铃,那么客戶端狀態(tài)就會變成CONNECTING狀態(tài)碴里,同時(shí)客戶端開始嘗試連接服務(wù)端,連接成功后上真,客戶端狀態(tài)變?yōu)镃ONNECTED咬腋,通常情況下,由于斷網(wǎng)或其他原因睡互,客戶端與服務(wù)端之間會出現(xiàn)斷開情況根竿,一旦碰到這種情況,Zookeeper客戶端會自動進(jìn)行重連服務(wù)就珠,同時(shí)客戶端狀態(tài)再次變成CONNCTING寇壳,直到重新連上服務(wù)端后,狀態(tài)又變?yōu)镃ONNECTED妻怎,在通常情況下壳炎,客戶端的狀態(tài)總是介于CONNECTING 和CONNECTED 之間。但是逼侦,如果出現(xiàn)諸如會話超時(shí)冕广、權(quán)限檢查或是客戶端主動退出程序等情況疏日,客戶端的狀態(tài)就會直接變更為CLOSE狀態(tài)。

5.3.2 會話創(chuàng)建

Session是Zookeeper中的會話實(shí)體撒汉,代表了一個(gè)客戶端會話沟优,其包含了如下四個(gè)屬性

  1. sessionID。會話ID睬辐,唯一標(biāo)識一個(gè)會話挠阁,每次客戶端創(chuàng)建新的會話時(shí),Zookeeper都會為其分配一個(gè)全局唯一的sessionID溯饵。
  2. TimeOut侵俗。會話超時(shí)時(shí)間,客戶端在構(gòu)造Zookeeper實(shí)例時(shí)丰刊,會配置sessionTimeout參數(shù)用于指定會話的超時(shí)時(shí)間隘谣,Zookeeper客戶端向服務(wù)端發(fā)送這個(gè)超時(shí)時(shí)間后,服務(wù)端會根據(jù)自己的超時(shí)時(shí)間限制最終確定會話的超時(shí)時(shí)間啄巧。
  3. TickTime寻歧。下次會話超時(shí)時(shí)間點(diǎn),為了便于Zookeeper對會話實(shí)行”分桶策略”管理秩仆,同時(shí)為了高效低耗地實(shí)現(xiàn)會話的超時(shí)檢查與清理码泛,Zookeeper會為每個(gè)會話標(biāo)記一個(gè)下次會話超時(shí)時(shí)間點(diǎn),其值大致等于當(dāng)前時(shí)間加上TimeOut澄耍。
  4. isClosing噪珊。標(biāo)記一個(gè)會話是否已經(jīng)被關(guān)閉,當(dāng)服務(wù)端檢測到會話已經(jīng)超時(shí)失效時(shí)齐莲,會將該會話的isClosing標(biāo)記為”已關(guān)閉”痢站,這樣就能確保不再處理來自該會話的心情求了。

Zookeeper為了保證請求會話的全局唯一性选酗,在SessionTracker初始化時(shí)阵难,調(diào)用initializeNextSession方法生成一個(gè)sessionID,之后在Zookeeper運(yùn)行過程中星掰,會在該sessionID的基礎(chǔ)上為每個(gè)會話進(jìn)行分配多望,初始化算法如下

    public static long initializeNextSession(long id) {
      long nextSid = 0;
      // 無符號右移8位使為了避免左移24后嫩舟,再右移8位出現(xiàn)負(fù)數(shù)而無法通過高8位確定sid值
      nextSid = (System.currentTimeMillis() << 24) >>> 8;
      nextSid = nextSid | (id << 56);
      return nextSid;
    }

5.3.3 會話管理

Zookeeper的會話管理主要是通過SessionTracker來負(fù)責(zé)氢烘,其采用了分桶策略(將類似的會話放在同一區(qū)塊中進(jìn)行管理)進(jìn)行管理,以便Zookeeper對會話進(jìn)行不同區(qū)塊的隔離處理以及同一區(qū)塊的統(tǒng)一處理家厌。

分捅策略

5.4 數(shù)據(jù)節(jié)點(diǎn) Znode

在Zookeeper中播玖,“節(jié)點(diǎn)"分為兩類,第一類同樣是指構(gòu)成集群的機(jī)器饭于,我們稱之為機(jī)器節(jié)點(diǎn)蜀踏;第二類則是指數(shù)據(jù)模型中的數(shù)據(jù)單元维蒙,我們稱之為數(shù)據(jù)節(jié)點(diǎn)一一ZNode。
Zookeeper將所有數(shù)據(jù)存儲在內(nèi)存中果覆,數(shù)據(jù)模型是一棵樹(Znode Tree)颅痊,由斜杠(/)的進(jìn)行分割的路徑,就是一個(gè)Znode局待,例如/foo/path1斑响。每個(gè)上都會保存自己的數(shù)據(jù)內(nèi)容,同時(shí)還會保存一系列屬性信息钳榨。


節(jié)點(diǎn)
5.4.1 節(jié)點(diǎn)類型

在Zookeeper中舰罚,node可以分為持久節(jié)點(diǎn)和臨時(shí)節(jié)點(diǎn)和順序節(jié)點(diǎn)三大類。
可以通過組合生成如下四種類型節(jié)點(diǎn)
1. PERSISTENT
持久節(jié)點(diǎn),節(jié)點(diǎn)創(chuàng)建后便一直存在于Zookeeper服務(wù)器上薛耻,直到有刪除操作來主動清楚該節(jié)點(diǎn)营罢。
2. PERSISTENT_SEQUENTIAL
持久順序節(jié)點(diǎn),相比持久節(jié)點(diǎn),其新增了順序特性饼齿,每個(gè)父節(jié)點(diǎn)都會為它的第一級子節(jié)點(diǎn)維護(hù)一份順序饲漾,用于記錄每個(gè)子節(jié)點(diǎn)創(chuàng)建的先后順序。在創(chuàng)建節(jié)點(diǎn)時(shí)候醒,會自動添加一個(gè)數(shù)字后綴能颁,作為新的節(jié)點(diǎn)名,該數(shù)字后綴的上限是整形的最大值倒淫。
3.EPEMERAL
臨時(shí)節(jié)點(diǎn)伙菊,臨時(shí)節(jié)點(diǎn)的生命周期與客戶端會話綁定,客戶端失效敌土,節(jié)點(diǎn)會被自動清理镜硕。同時(shí),Zookeeper規(guī)定不能基于臨時(shí)節(jié)點(diǎn)來創(chuàng)建子節(jié)點(diǎn)返干,即臨時(shí)節(jié)點(diǎn)只能作為葉子節(jié)點(diǎn)兴枯。
4.EPEMERAL_SEQUENTIAL
臨時(shí)順序節(jié)點(diǎn),在臨時(shí)節(jié)點(diǎn)的基礎(chǔ)添加了順序特性。

5.5 版本——保證分布式數(shù)據(jù)原子性操作

每個(gè)數(shù)據(jù)節(jié)點(diǎn)都具有三種類型的版本信息矩欠,對數(shù)據(jù)節(jié)點(diǎn)的任何更新操作都會引起版本號的變化财剖。

version– 當(dāng)前數(shù)據(jù)節(jié)點(diǎn)數(shù)據(jù)內(nèi)容的版本號
cversion– 當(dāng)前數(shù)據(jù)子節(jié)點(diǎn)的版本號
aversion– 當(dāng)前數(shù)據(jù)節(jié)點(diǎn)ACL變更版本號

上述各版本號都是表示修改次數(shù),如version為1表示對數(shù)據(jù)節(jié)點(diǎn)的內(nèi)容變更了一次癌淮。即使前后兩次變更并沒有改變數(shù)據(jù)內(nèi)容躺坟,version的值仍然會改變。version可以用于寫入驗(yàn)證乳蓄,類似于CAS咪橙。

5.6watcher事件監(jiān)聽器

ZooKeeper允許用戶在指定節(jié)點(diǎn)上注冊一些Watcher,當(dāng)數(shù)據(jù)節(jié)點(diǎn)發(fā)生變化的時(shí)候,ZooKeeper服務(wù)器會把這個(gè)變化的通知發(fā)送給感興趣的客戶端


監(jiān)聽

5.7 ACL 權(quán)限控制——保障數(shù)據(jù)的安全

ACL是Access Control Lists 的簡寫, ZooKeeper采用ACL策略來進(jìn)行權(quán)限控制,有以下權(quán)限:
CREATE:創(chuàng)建子節(jié)點(diǎn)的權(quán)限
READ:獲取節(jié)點(diǎn)數(shù)據(jù)和子節(jié)點(diǎn)列表的權(quán)限
WRITE:更新節(jié)點(diǎn)數(shù)據(jù)的權(quán)限
DELETE:刪除子節(jié)點(diǎn)的權(quán)限
ADMIN:設(shè)置節(jié)點(diǎn)ACL的權(quán)限

5.8 Paxos算法

Paxos算法是基于消息傳遞且具有高度容錯(cuò)特性的一致性算法媒咳,是目前公認(rèn)的解決分布式一致性問題最有效的算法之一舀患。(其他算法有二階段提交、三階段提交等)

六、ZooKeeper 可以做什么?

  • 分布式服務(wù)注冊與訂閱

    在分布式環(huán)境中,為了保證高可用性擦囊,通常同一個(gè)應(yīng)用或同一個(gè)服務(wù)的提供方都會部署多份,達(dá)到對等服務(wù)嘴办。而消費(fèi)者就須要在這些對等的服務(wù)器中選擇一個(gè)來執(zhí)行相關(guān)的業(yè)務(wù)邏輯瞬场,比較典型的服務(wù)注冊與訂閱,代表:dubbo涧郊。


    注冊中心
  • 分布式配置中心
    發(fā)布與訂閱模型贯被,即所謂的配置中心,顧名思義就是發(fā)布者將數(shù)據(jù)發(fā)布到ZK節(jié)點(diǎn)上妆艘,供訂閱者獲取數(shù)據(jù)彤灶,實(shí)現(xiàn)配置信息的集中式管理和動態(tài)更新。代表:百度的disconf批旺。
    github:https://github.com/knightliao/disconf

  • 命名服務(wù)
    在分布式系統(tǒng)中幌陕,通過使用命名服務(wù),客戶端應(yīng)用能夠根據(jù)指定名字來獲取資源或服務(wù)的地址汽煮,提供者等信息搏熄。被命名的實(shí)體通常可以是集群中的機(jī)器暇赤,提供的服務(wù)地址心例,進(jìn)程對象等等——這些我們都可以統(tǒng)稱他們?yōu)槊郑∟ame)。其中較為常見的就是一些分布式服務(wù)框架中的服務(wù)地址列表鞋囊。通過調(diào)用ZK提供的創(chuàng)建節(jié)點(diǎn)的API止后,能夠很容易創(chuàng)建一個(gè)全局唯一的path,這個(gè)path就可以作為一個(gè)名稱溜腐。

    命名

  • 分布式鎖
    分布式鎖译株,這個(gè)主要得益于ZooKeeper為我們保證了數(shù)據(jù)的強(qiáng)一致性。鎖服務(wù)可以分為兩類挺益,一個(gè)是保持獨(dú)占歉糜,另一個(gè)是控制時(shí)序。
    所謂保持獨(dú)占矩肩,就是所有試圖來獲取這個(gè)鎖的客戶端现恼,最終只有一個(gè)可以成功獲得這把鎖。通常的做法是把zk上的一個(gè)znode看作是一把鎖黍檩,通過create znode的方式來實(shí)現(xiàn)叉袍。所有客戶端都去創(chuàng)建 /distribute_lock 節(jié)點(diǎn),最終成功創(chuàng)建的那個(gè)客戶端也即擁有了這把鎖刽酱。
    控制時(shí)序喳逛,就是所有視圖來獲取這個(gè)鎖的客戶端,最終都是會被安排執(zhí)行棵里,只是有個(gè)全局時(shí)序了润文。做法和上面基本類似,只是這里 /distribute_lock 已絆預(yù)先存在殿怜,客戶端在它下面創(chuàng)建臨時(shí)有序節(jié)點(diǎn)(這個(gè)可以通過節(jié)點(diǎn)的屬性控制:CreateMode.EPHEMERAL_SEQUENTIAL來指定)典蝌。Zk的父節(jié)點(diǎn)(/distribute_lock)維持一份sequence,保證子節(jié)點(diǎn)創(chuàng)建的時(shí)序性,從而也形成了每個(gè)客戶端的全局時(shí)序

  • Master選舉

  • 負(fù)載均衡

    負(fù)載均衡

參考

  • 《從Paxos到Zookeeper 》
  • 《ZooKeeper深入淺出 》

不知道大家是否還記的文章開頭的兩個(gè)問題头谜,礙于本文篇幅的原因這里不再一一解答骏掀,想要了解答案,想往架構(gòu)師進(jìn)發(fā)的小伙伴可以加群895244712一起交流學(xué)習(xí)柱告,視頻我已經(jīng)整理好放在群文件了截驮。

最后,如有幫助請轉(zhuǎn)發(fā)际度,點(diǎn)贊葵袭。您的拇指是對我最好的支持!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末乖菱,一起剝皮案震驚了整個(gè)濱河市坡锡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌窒所,老刑警劉巖娜氏,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異墩新,居然都是意外死亡贸弥,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進(jìn)店門海渊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來绵疲,“玉大人,你說我怎么就攤上這事臣疑】” “怎么了?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵讯沈,是天一觀的道長郁岩。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么问慎? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任萍摊,我火速辦了婚禮,結(jié)果婚禮上如叼,老公的妹妹穿的比我還像新娘冰木。我一直安慰自己,他們只是感情好笼恰,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布踊沸。 她就那樣靜靜地躺著,像睡著了一般社证。 火紅的嫁衣襯著肌膚如雪逼龟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天追葡,我揣著相機(jī)與錄音审轮,去河邊找鬼。 笑死辽俗,一個(gè)胖子當(dāng)著我的面吹牛疾渣,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播崖飘,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼榴捡,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了朱浴?” 一聲冷哼從身側(cè)響起吊圾,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎翰蠢,沒想到半個(gè)月后项乒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡梁沧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年檀何,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片廷支。...
    茶點(diǎn)故事閱讀 40,144評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡频鉴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出恋拍,到底是詐尸還是另有隱情垛孔,我是刑警寧澤,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布施敢,位于F島的核電站周荐,受9級特大地震影響狭莱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜概作,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一腋妙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧仆嗦,春花似錦、人聲如沸先壕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽垃僚。三九已至集绰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間谆棺,已是汗流浹背栽燕。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留改淑,地道東北人碍岔。 一個(gè)月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像朵夏,于是被迫代替她去往敵國和親蔼啦。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評論 2 355

推薦閱讀更多精彩內(nèi)容