天天看點

反常理,反直覺,區塊鍊是怎樣的一種“分布式系統”

我們經常看到“區塊鍊是分布式系統”的說法,并推論出區塊鍊先天具備分布式系統的優勢,仿佛作為分布式系統,規模就該足夠大,資料就該足夠分散。

事實上,典型區塊鍊有很多特征和常見的分布式系統不同,甚至是相悖的,為此,區塊鍊曾被戲稱為“最慢的分布式資料庫”。

其實區塊鍊之是以難以了解,其中一個原因是其設計哲學的“反常理、反直覺”。筆者本人曾多年在網際網路海量服務領域裡踩坑,然後轉向區塊鍊領域深入研究,也經曆過一陣子的觀念切換期。

本文不打算全面講述分布式系統原理和曆史,那能寫幾本書。這裡打算從常見的、被人廣泛認知的網際網路分布式系統出發,聊聊“分布式系統”和區塊鍊有什麼異同,對技術和設計的要求有哪些路徑分支。

經典的分布式著作《分布式系統概念與設計》中,對“分布式系統”給出的定義其實很籠統:分布式系統是一個硬體或軟體元件分布在不同的網絡計算機上,彼此之間僅僅通過消息傳遞進行通信和協調的系統。

簡而言之,隻要不是運作在一台機器上或一個程序裡的系統,都可以是分布式系統。

比如,大型網站、APP、全民IM社交軟體的支撐系統,基于X86體系的新型金融基礎設施,都可以是分布式系統。

至于這個分布式系統是屬于一個機構的,還是屬于多個不同機構維護的,并不是這個定義的重點。

網際網路海量服務系統之道

(提示:已經比較熟悉網際網路海量設計的讀者,可以直接跳過本節)

如果要求一個網際網路服務的架構師,在面對山呼海嘯的請求量、儲存無限增長的資料的同時,提供良好的使用者體驗,保證延時很短的響應表現,這位架構師腦子裡蹦出來的通常是“分層設計”、“冷熱分離”、“平行擴充”、“并行處理”、“分庫分表”等等關鍵字。

網際網路海量服務的架構通常是分層的,比如接入層、服務層、資料層等。在接入層根據各種政策進行負載均衡和靈活的路由分發,服務可以按功能分組。比如:

使用者要改個人資料,請求發給資料服務;

使用者浏覽網頁,請求查詢服務吐資料;

使用者要發帖了,轉給内容服務;

使用者要下單,該交易伺服器接手了,每個服務隻處理一部分業務邏輯,互相之間通過遠端接口互相調用,且本身通常是“無狀态”的,不受自身和其他服務處理狀态的牽制,這種高内聚和松耦合的設計,利于針對不同服務的特性和負載,進行特定優化和靈活部署;

最後,資料存儲是“分片”的,俗稱“分庫分表”,根據使用者辨別、業務類型等規則,将資料分攤在不同的資料庫執行個體中,每個資料庫執行個體上隻有“部分”資料,僅僅是資料的“子集”。

以UGC、社交、富文本、視訊内容為主的網際網路服務,對“交易事務性”要求并不那麼強,其“分布式”更多的是追求将計算和資料均勻分散在多台伺服器上,利用更多的CPU、更大的帶寬、更大的記憶體、更大的磁盤空間來處理請求。

一組伺服器不夠了,立刻增加一組,平行擴容和多活特性表現得淋漓盡緻。整個體系會有一些主備和備援,更多是為了滿足服務品質、可用性、備份方面的要求。

電商以及一些和金融、支付相關的流程會強調ACID事務性,采用的分布式一緻性算法,如Raft、Paxos等,主要是追求多子產品之間的最終一緻性和系統穩定性。

畢竟在同一個機構裡的系統,對抗欺詐的要求并不會太苛刻,而且可以根據特定的業務流程将交易分類,将單個事務控制在有限的範圍内(如隻有使用者向商戶單向轉賬),事務和事務之間進行清晰地隔離,這樣也比較容易進行平行擴充。

如上圖所示,一個典型的多層結構的網際網路服務,子產品衆多,計算和存儲分布都比較均勻,哪個子產品成為瓶頸,就去增加哪個子產品的硬體資源,進行業務路由配置和必要的資料遷移就是了。

像分布式資料庫、大資料叢集、或者BT網絡、CDN這些“分布式系統”,大多也是遵循“将使用者和資料分散到不同的實體裝置上”這個原則,達到簡單的“堆硬體”即可平行擴充的效果。

硬體越多,技術上的“規模效應”越顯著,即存儲量更大、計算能力更強、總帶寬越多,能服務的使用者就越多。

最重要的是,整個服務大部分是在同一個機構裡,由同一個公司的團隊維護,服務和服務之間并不需要解決“信任”的問題,預設信任其他服務的接口給出的結果,簡單校驗後立刻繼續處理,整個系統就是要“快”,要“穩”。

如果有一些合作類的接口暴露給外部公司,隻需要確定接口層的性能、安全、穩定,以及滿足合作規則即可。

“帶着鎖鍊跳舞”的區塊鍊

再看區塊鍊,首先整個網絡并不是隻有一個機構參與,節點都可能歸屬不同的機構,大家一起共同維護網絡,共同對交易達成共識。

區塊鍊的使命是突破機構邊界,解決機構之間的信任和博弈問題,如果隻在一個機構内“家養”一個區塊鍊系統,固然可以運作,但收效未必最佳。

區塊鍊體系裡,為了保證資料可追溯和可驗證,避免少數節點篡改資料影響全網,每個節點儲存全部資料,而不是像網際網路服務這樣“分庫分表”。

讓我們算一下,如果有一千萬個使用者,在網際網路系統裡分成10個資料庫執行個體儲存,則每個資料庫執行個體隻儲存100萬使用者的資料。

即使每個資料庫執行個體都是“一主兩備”,那麼總的資料開銷也隻是原始資料的3倍。

而經典的區塊鍊設計是,每個節點都如數儲存一千萬使用者的所有資料,且全網節點越多,儲存的資料副本就越多。

如全網有100個節點,則全網總的資料存儲開銷是原始資料的100倍;如有200個節點,全網總的資料存儲則達到原始資料的200倍……以此類推,挺觸目驚心。

極端情況下,如果把整個地球的資料都上鍊,鍊上有1萬個節點,那麼相當于我們有了1萬個地球......然而我們并沒有這麼多資源吧。

區塊鍊的資料結構本身也是很有意思的一個環節。區塊之間是鍊式關系,新的區塊必須基于舊的區塊生成。

智能合約生成狀态資料是全局性的,常常用類似帕特裡夏樹、merkle樹這種複雜的資料結構進行維護,以便全網追溯、驗證和計算。

資料環環相扣,仿佛“鐵闆一塊”,使得按冷熱特征、時間和使用者等次元切分資料有相當的挑戰性,既要使資料可以分布到不同的存儲裡,又要保證可以快速通路,保證盤根錯節的追溯驗證。工程難度很大。

交易層面,在一個互相沒有強信任關系的網絡裡,且處理的是大機率和“價值”有關系的交易,區塊鍊尤其強調交易的全局事務性,保證全網一緻性,且為了避免有作惡節點僞造假資料,所有的交易都會在共識機制和網絡同步驅動下,在所有的節點上進行排序、運算和校驗。

在支援智能合約的區塊鍊上,每個智能合約被交易調用時,都會在所有

手機号出售

節點上把合約代碼跑一遍,以確定在每個節點上生成資料的過程是公認的、運作結果是一緻的。

可見,區塊鍊并不能把計算量分攤到不同的伺服器上,所有的節點都是“複讀機”,這就意味着增加節點,也不會增加全網并行計算能力,就算是全網有一萬台計算機,速度也跟隻有一台是一樣的。

如果把這種區塊鍊稱為“世界計算機”,可算是全世界步驟最統一、備援度最高、速度最慢的世界計算機了。

區塊鍊系統的核心是共識算法。

POW挖礦是礦工用算力解一個難題,以争到記賬權,再進行記賬,并期盼自己的記賬結果成為最長鍊。

POW算法是出了名的又慢又耗電;

POS權益類共識,由一批“富翁”抵押資産以獲得記賬權,輪流記賬,不需要算力競争,性能表現好一些,但依舊是有輪流打包出塊然後全網最終确認的過程;

PBFT(實用性拜占庭)共識,需要記賬者多次往返互動,大多數人參與到多階段的确認,才能達到最終狀态。

總的來說,和網際網路服務追求的“無狀态”不同,共識服務是“有狀态”的,每種共識算法都需要參照網絡、資料、記賬者參與度、鍊目前狀态(如“區塊高度”和“共識階段”)等等多元度的資訊進行決策。

記賬節點越多,協作成本越高,尤其是典型的PBFT算法,在節點增多時,共識會越來越慢,交易延遲會越來越高。

如果讓節點内部也“叢集化”,采用“多層分布式架構”,是否可以實作類似網際網路海量服務系統這樣的可平行擴充呢?比如,将虛拟機改為多執行個體,并行計算交易,這樣就可以解決計算瓶頸問題。

但計算越快,機關時間可以産生的資料越多,這樣也要求硬碟存儲更多的資料,而硬碟的容量和IO速度是有限的。

同時,計算快了,節點也會向網絡廣播更多的資料,節點公網互聯的帶寬通常不會太大,延時一般也比較明顯(幾十毫秒起)。

于是,節點和節點之間互動又會命中網絡速度的瓶頸,共識時延和資料同步時間變長,節點們就像一串綁在繩子上的螞蚱,誰也蹦不高。由于存儲和網絡這些硬條件的天花闆存在,叢集化的計算再快也沒有用了。

最後,節點叢集化确實可以使以節點為機關的服務處理能力有一定上升,同時也會帶來的架構上的額外複雜性和部署運維成本。

還是引用一個數錢的例子:

有一大堆錢讓十個人數,有兩種方法。

方法一,可以把錢分成十份,每個人數一份,這樣很快就數完了,人越多,數得越快,但是如果裡面有人數錯了,或者甚至偷錢,那就有問題了。

于是,為了資金安全,改成方法二,讓一個人整理出一疊錢,先數一遍,然後讓其他九個人也數一遍,每個人都驗算記賬後,再換個人整理出下一疊錢,重複上述節奏去數,這樣結果肯定是不會錯的,且能得到大家的公認。但參與數錢的人增加,并不會加速計數,反而有可能因為人多手雜導緻更慢。

方法一就是常見的網際網路分布式系統的做法,方法二是區塊鍊。

可見,目的不同,導緻設計哲學、系統結構、最終效果都不同。

如何把“好鋼用到刀刃上”

綜上所述,區塊鍊這種“分布式系統”,存儲成本和節點數同比線性增加,而計算效率不升反降,使整個系統顯得“貴”和“重”,這和網際網路服務的“輕快靈”相背而馳。最要命的是,難以通過增加硬體、帶寬、節點數來顯著提升并行處理能力和存儲量。

但區塊鍊的“網絡規模效應”并不展現在硬體和計算上,而是展現在因為“共識”和“信任”上。

區塊鍊通過複雜的算法和博弈,建構了一種可信網絡,使得更多人願意參與到網絡裡,共同貢獻資料和維護網絡,展現“協作共赢”這個價值效應。

這樣也給我們一個重要啟示:既然區塊鍊的計算和存儲成本是很高的,其目的是為了達到共識,那麼,我們應該讓區塊鍊幹最該幹的事情。

1、哪些資料可以“上鍊”?

隻有多方要在交易過程中用到的、必須共享的關鍵資料要上鍊,比如公共賬本的賬目。

視訊、檔案、圖檔、大規模的業務資料,可以生成摘要與交易資料關聯,其本體通過其他管道(如FTP、分布式檔案系統等)進行交換。

比如下棋,隻需要把棋局結果放到鍊上,或者把每一步的資料算個摘要放到鍊上,并不需要每一步都記錄到鍊上(除非認為這也是非常關鍵的資訊)。

畢竟每一筆放到“鍊上”的資料,都會占用所有節點的硬碟。

2、合約裡寫什麼邏輯?

應該是寫多方共同參與、協作記賬、必須全局共識的關鍵邏輯,而不是牽涉密集計算的邏輯。

比如,進行複雜查詢或模組化分析,可以把鍊上的資料導出來放在鍊下去做,而不是寫在合約裡。要清楚,你寫的每一行代碼,再不是隻在自己的服務上跑一次了,而是會在鍊上所有參與者的節點上跑起來,多寫一行代碼就會多消耗大家的一點CPU。

是以,區塊鍊上會有類似“Gas上限”這樣的機制,來控制合約的代碼規模。新一代的合約引擎,更是考慮隻提供有限的、可以定制化的商業規則實作,而不是完全的開放式程式設計。

作為開發者,是面向“自己的電腦”程式設計,還是面向“大家的電腦”程式設計,這就是網際網路海量服務系統和區塊鍊最大的不同。

開發者必須切換思維模式,切忌濫用區塊鍊上寶貴的計算、存儲、網絡資源,避免有意或無意的“公地悲劇”,而是精打細算,從全局權衡,找出協作模式和資料共享裡的“最大公約數”,把好鋼用到刀刃上。

性能也不是什麼大問題

區塊鍊的規模化、并發能力,依舊是業界非常關注的研究方向。網際網路海量分布式系統的一些思想,對區塊鍊的優化也有很重要的參考意義,包括平行擴充、分庫分表、冷熱分離、服務叢集、負載均衡等等。

現在我們在研究區塊鍊優化時,常常有一種感覺,就是把之前在網際網路業裡解決經典“C1000K問題(應對百萬級的并發量)”的過程再來一遍。

技術優化方案百花齊放,諸如FISCO BCOS的多群組和并行多鍊架構,基于DAG的交易并發模型,以及行業熱議的交易分片、Layer1/2多層網絡、鍊外通道如閃電網絡等。

因為要滿足區塊鍊苛刻的信任和安全要求,實施這些方案成為“帶着鎖鍊跳舞”的艱辛工作。在不遠的未來,在力求保證“信任”、“一緻性”、“事務性”、“安全”等大前提下,區塊鍊系統也可以具備可觀的可擴充性,突破或逼近“不可能三角”的極限并不是夢。

目前,在保證金融級業務的正确性、穩定性的前提下,FISCO BCOS已經做到在PBFT共識、16個節點規模、采用智能合約實作業務邏輯的條件下,達到單鍊2萬多的TPS(硬體條件比較理想的壓測環境)。

如果開啟多群組、多鍊跨鍊、點對點通道等模式,更有顯著的平行擴充效果,滿足目前的業務需求已經沒什麼問題了,隻要有足夠的硬體資源投入,進行合理的排程,百萬千萬TPS也不是夢。

最後總結一下,我們認為區塊鍊是一種特殊的“分布式系統”,要透徹地了解區塊鍊,應該清晰地、就事論事地與其他類型分布式系統進行區分,理清各自的本質和設計哲學,避免混淆和迷惑。

說到底,“分布式系統”本身就是一門博大精深的學科,包羅萬象,并不能從一而論,而是有太多的精彩和技術路徑需要去學習和發掘。