ONOS系統(tǒng)架構(gòu)之高可用實現(xiàn)方案的演進(jìn)

上篇文章《ONOS高可用性和可擴(kuò)展性實現(xiàn)初探》講到了ONOS系統(tǒng)架構(gòu)在高可用、可擴(kuò)展方面技術(shù)概況,提到了系統(tǒng)在分布式集群中如何保證數(shù)據(jù)的一致性。在數(shù)據(jù)最終一致性方面,ONOS采用了Gossip協(xié)議,這一部分的變化不大,而在強(qiáng)一致性方案的選擇方面則在不斷進(jìn)行調(diào)整,其主要原因是分布式系統(tǒng)中強(qiáng)一致性對系統(tǒng)性能影響較大,而且現(xiàn)有的支持Paxos算法的實現(xiàn)不多。本文承接上一篇提出的一個問題:ONOS為什么從開始使用ZooKeeper轉(zhuǎn)到Hazelcast,而最終選擇了Raft?是不是之前的選擇導(dǎo)致系統(tǒng)缺陷?亦或是在某些條件下無法滿足性能需求?且看下文為你慢慢道來。

在開始之前,先簡單的介紹一下ZooKeeper、Hazelcast和Raft,提供一些資料方便大家閱讀。

ZooKeeper,Hadoop生態(tài)系統(tǒng)中知名的分布式協(xié)作系統(tǒng),是Google的Chubby一個開源的實現(xiàn),以C/S方式提供服務(wù),應(yīng)用場景包括配置維護(hù)、名字服務(wù)、分布式同步、組服務(wù)等???蛻舳?與服務(wù)器(Follower/Leader)以Watch/Callback的方式進(jìn)行交互,如圖1所示流程,可參考相關(guān)實例代碼。

Hazelcast是一種內(nèi)存數(shù)據(jù)網(wǎng)格(IMDG: In-Memory Data Grid),網(wǎng)格中所有的節(jié)點是以Peer-to-Peer的方式組建集群,并且所有數(shù)據(jù)置于內(nèi)存中以提高訪問性能[ Hadelcast架構(gòu)介紹文檔]。Hazelcast提供了通用的數(shù)據(jù)結(jié)構(gòu)(如Map, List, Queue等)和簡單的API進(jìn)行數(shù)據(jù)操作,可以直接引入jar包進(jìn)行實現(xiàn),可以參考下文提供的相關(guān)實例代碼。

Raft是為了解決Paxos算法的可讀性以及實現(xiàn)中拋棄一些細(xì)節(jié)形成的等價于Multi-Paxos算法。它依賴于復(fù)制狀態(tài)機(jī)(Replicated?State?Machine),通過Replicated?Log將操作指令復(fù)制到各個節(jié)點,然后各節(jié)點在本地按相同的順序執(zhí)行相同的命令,產(chǎn)生一致的狀態(tài),圖2展示的是Raft狀態(tài)機(jī)。

根據(jù)上面的介紹,我們對這些方案有了初步的了解。現(xiàn)在假設(shè)我們是該系統(tǒng)的設(shè)計者,面臨對這三個方案技術(shù)方案進(jìn)行選型,我們首先需要對這些方案進(jìn)行對比,具體如表1所示:

從解決問題的角度來說,這三個方案都可以解決ONOS在分布式一致性協(xié)作方面的問題,因為算法證明了這些方案都是“正確”的,除非實現(xiàn)上有Bug。就算法的性能來說,差異不是很大。Paxos算法(一種基于消息傳遞模型的一致性算法),它能保證在一個分布式數(shù)據(jù)庫系統(tǒng)中,如果各節(jié)點的初始狀態(tài)一致,每個節(jié)點都執(zhí)行相同的操作序列,那么他們最后能得到一個一致的狀態(tài)。而Raft算法是等價于Multi-Paxos的算法,它主要解決的是Paxos晦澀的描述,以及Paxos的實現(xiàn)不能真正意義上的完全正確(實現(xiàn)上無法用公式證明)。這兩個算法雖然在實現(xiàn)上差別很大,比如一致性實現(xiàn)中角色的定義,比如ZooKeeper中定義了Leader/Follower,Raft定義了Candidate/Leader/Follower角色,但其最核心的兩個關(guān)鍵活動,一個是選舉,其目的就是從分布的節(jié)點中選出Leader節(jié)點作為一致性的參考標(biāo)桿,其它的Follower就成為“鏡像”。選舉只有在初始化或有Leader退出/失效時才發(fā)生,在分布式系統(tǒng)中,節(jié)點失效出現(xiàn)的頻次很低,而且選舉動作都是可以在秒級別能完成的,對系統(tǒng)的性能影響不大,不明顯,實際情況中與系統(tǒng)節(jié)點數(shù)的奇/偶性更相關(guān),比如4個節(jié)點或6個節(jié)點選舉時間可能比13個節(jié)點選舉時間更長。另外一個是同步,其目的是通過復(fù)制數(shù)據(jù)/操作來達(dá)到所有的Follower都能產(chǎn)生一致的結(jié)果,只要狀態(tài)有更新(比如寫操作),那么就會觸發(fā)同步動作,同步意味著數(shù)據(jù)的復(fù)制以及消息的傳遞,從分布式架構(gòu)來說,在讀寫IO方面這三種實現(xiàn)方式都相差不多。從這個角度來說,算法不是決定因素。

大家可能會問:既然算法都差不多了,就沒有必要在ONOS實現(xiàn)上大動手腳了。其實,從上表我們可以知道,當(dāng)初選擇ZooKeeper作為Prototype?1的首選,主要是因為ZooKeeper成熟穩(wěn)定,它在Hadoop生態(tài)圈是鼎鼎有名的高性能、分布式的應(yīng)用協(xié)調(diào)服務(wù)的首選。從ONOS的Prototype?1的實現(xiàn)來看,ZooKeeper確實滿足了分布式集中控制的需求,另外一方面,在其實驗過程中,驗證系統(tǒng)的性能時,很多數(shù)據(jù)是全局靜態(tài)的,比如Flow?Rule在實際的應(yīng)用中是通過控制器以Lazy的方式下發(fā)到交換設(shè)備中,那么這些數(shù)據(jù)可以提前在ZooKeeper中準(zhǔn)備好,只要實驗中不進(jìn)行交換設(shè)備的動態(tài)增加或者移除,不會影響到整體性能。也就是說,在Prototype?1中主要關(guān)注SDN的概念在ONOS上能發(fā)揮到何種程度,而不關(guān)心交換設(shè)備動態(tài)增加、刪除等場景。

也就是說當(dāng)有數(shù)據(jù)大量更新時,ZooKeeper則會出現(xiàn)性能問題,這主要因為ZooKeeper是以服務(wù)的形式來保障數(shù)據(jù)的一致性的。相對于ONOS來說,ZooKeeper是它的一個依賴子系統(tǒng),因此在部署ONOS之外還要單獨部署ZooKeeper服務(wù),如圖3所示的Client與Server之間的讀寫模型。由于ZooKeeper中所有的數(shù)據(jù)都以ZNode表示,這些ZNode存儲在ZooKeeper的Server上,Client要讀的數(shù)據(jù)需要跨JVM訪問Server。這樣ONOS?Instance就變成了zClient,那么當(dāng)ONOS不同實例間需要同步數(shù)據(jù)時,需要通過TCP的方式從zServer上請求數(shù)據(jù),這就導(dǎo)致了ONOS的性能會急劇下降,另外,ZooKeeper的zNode對數(shù)據(jù)大小有限制(zNode數(shù)據(jù)大小不能超過1M)。所以說ZooKeeper以服務(wù)的模式提供分布式一致性,對于ONOS有太多限制,而這時Hazelcast解決了這些問題。

Hazelcast是peer-to-peer的模式,直接應(yīng)用其library以embedded的方式來實現(xiàn),也就是每個ONOS Instance可以作為一個peer,ONOS的業(yè)務(wù)數(shù)據(jù)就在同一個JVM中,如圖4所示(Hazelcast也能提供C/S模式的服務(wù))。更重要的是,Hazelcast是一個IMDG(In-Memory Data Grid),提供了很方便的接口進(jìn)行數(shù)據(jù)操作,在性能上得到了很大的提升。但是,Hazelcast有個致命的問題,它還很不成熟,在版本升級中可能會不兼容。比如在ONOS1.1.0中依然有很多Hazelcast相關(guān)的Bug,這就意味著ONOS依賴于一個不成熟的庫,風(fēng)險會很大。實際上關(guān)鍵的因素是:Hazelcast是否能正確地實現(xiàn)Paxos算法還是一個未知數(shù),包括ZooKeeper的實現(xiàn)也不能被證明在算法上正確的,因為Paxos實在是太復(fù)雜了,能正確理解算法的人不多,更別談實現(xiàn)了。有人會覺得,不管怎樣Hazelcast會不斷改進(jìn)的,如果有問題直接提交Bug給Hazelcast不就解決了?或者說咱們也是做開源的,幫Hazelcast改進(jìn)為什么不行?原因是當(dāng)ONOS有了Hazelcast的Bug后就成了ONOS的Bug,解決這樣的Bug一方面是存在時間上的風(fēng)險,另外一方面也取決于Hazelcast是否會因為支持ONOS而進(jìn)行升級。萬一版本升級,出現(xiàn)不兼容現(xiàn)象,那么已經(jīng)部署的ONOS風(fēng)險就更大了。把風(fēng)險控制在自己能掌控的范圍之中才是ONOS社區(qū)首先考慮的。在這種情況下,Raft就成了不二之選了。

Raft是Multi-Paxos的一種等價算法,其實現(xiàn)可以通過狀態(tài)機(jī)(一種容錯機(jī)制)、日志副本和一致性模塊(Raft協(xié)議)之間的協(xié)同完成,這種簡單的模型抽象容易實現(xiàn)客戶端和數(shù)據(jù)在同一個JVM上,以實現(xiàn)Embedded的方案,具體架構(gòu)如圖5所示。由于目前在ONOS代碼中還沒有與Raft相關(guān)的實現(xiàn),但我們可以從ONOS項目的Sprint可以看出,在ONOS中首先需要解決的是替換掉Hazelcast,并且保留可擴(kuò)展的強(qiáng)一致性的存儲。另外,在維護(hù)設(shè)備的主從關(guān)系上,也需要Raft來實現(xiàn),因為選舉服務(wù)是Raft必備的功能。上篇文章也提到過Intent需要強(qiáng)一致性來保障,Intent數(shù)據(jù)是通過分布式隊列發(fā)送,因此也需要支持基于Raft的數(shù)據(jù)庫服務(wù)。

到目前為止,我們了解到了ONOS系統(tǒng)架構(gòu)中的高可用方案演進(jìn)的整個過程。在系統(tǒng)POC初期,ONOS關(guān)注的是SDN概念上的驗證,選擇了ZooKeeper滿足了基本的需求;接下來發(fā)現(xiàn)在HA方面存在性能問題,為了保證與ZooKeeper有同樣功能,而且性能優(yōu)先的原則,選擇了Hazelcast,而且它確實做到了。而Hazelcast的問題在于它是一個沒有被廣泛驗證過、不成熟的、還在不斷改進(jìn)的方案,ONOS不能依賴于這樣的一個方案,因此最終選擇了Raft。雖然要在ONOS中全面實現(xiàn)Raft還需要時日,但在這個時候選擇Raft是正確的、合理的。

ONOS已經(jīng)將Raft的實現(xiàn)提上日程,請參考官方的任務(wù)列表,我們共同期待ONOS中的Raft實現(xiàn)吧!個人認(rèn)為,ONOS在項目管理上做得非常優(yōu)秀,這也是ONOS脫穎而出的原因。?如果您有興趣,也加入到ONOS的開源社區(qū)吧,關(guān)注ONOS的成長,一起推動SDN的發(fā)展!

參考資料

ZooKeeper官方網(wǎng)站:http://zookeeper.apache.org/

ZooKeeper相關(guān)介紹:http://www.oschina.net/p/zookeeper

ZooKeeper的客戶端Kazoo:http://openinx.github.io/2014/06/07/learning-from-kazoo/

ZooKeeper分布式鎖實例代碼:http://ifeve.com/zookeeper-lock/

Hazelcast官方網(wǎng)站:http://hazelcast.org/

Hadelcast架構(gòu)介紹文檔:http://docs.hazelcast.org/docs/latest/manual/html/overview.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容