轉載自(4條消息) 聊聊計算和存儲分離_lizhao007-CSDN博客
2.何為計算?何為存儲?
要了解計算和存儲分離到底是什么,那么我們就需要理解什么是計算,什么是存儲。
計算這個單詞有運算之義,和數學的關系密不可分。大家回想一下以前數學考試的時候,那一道道的數學題怎么得出結果的,這一過程其實稱之為計算。那我們這里談論的其實是計算機計算,所以我們可以得出通過計算機得到問題的結果這個就叫做計算機計算,也就是我們這里所談論的"計算"。
對於存儲來說,這個概念比較難以定義,很多人都簡單的認為這個是硬盤,U盤等。但其實在我們的計算機計算過程中和存儲是密不可分的,我們知道CPU是由控制器、運算器和寄存器組成的,我們在運行一段程序的時候我們的指令是存儲在我們的存儲器的,我們所執行的每一個步驟都和存儲分離不開。比如我們以前考試的時候選擇題,大家關心的只是你選擇是否正確,不會關心你的運算過程,你的運算結果可以看做是硬盤,需要持久化給評卷人看,而你的計算過程類似草稿紙,雖然不需要給評卷人看,但是一樣的是實實在在的寫在了紙上。
上面我們說了在計算機中計算和存儲其實是分離不開的,我們想想如果將計算和存儲分離開來,通過高速網絡進行交互,那么我們的CPU的每一條指令都需要通過網絡傳輸,而我們的網絡傳輸和我們當前的CPU速度完全不匹配,所以我們的計算和存儲分離其實是一個偽需求,當然在未來的某一天如果我們的網絡傳輸的時間可以忽略不計,計算和存儲分離也就能真正的實現了。
計算和存儲分離既然是一個偽需求,那為什么這么多人還在提及呢?那就需要重新再定義一下他們的含義,我們將計算過程中的存儲歸納為計算,只關注問題和結果,這就是我們新的“存儲”的定義,就類似我們考試的時候草稿紙不需要存放,可以任意撕毀一樣。
那這里我們來做一個最終的定義,我們后面所講的“存儲”都是需要持久化的,可以是U盤,硬盤,網盤等等,我們所講的“計算”其實就是我們的計算過程所需要的CPU和內存等。
3.為何需要計算和存儲分離
計算和存儲分離並不是現在才出現的一個新名詞,在20年前就有NAS-網絡附加存儲這個東西,本質上也就是使用TCP/IP協議的以太網文件服務器。當時如果想要大規模的存儲,就會讓服務器將數據保存到NAS這個上面,但是NAS價格及其昂貴,並且擴展比較困難,NAS也就不適用於高速發展的互聯網應用。
這個時候谷歌摒棄了之前的觀念“移動存儲到計算”,采取了“移動計算到存儲的觀念”,將計算和存儲耦合了,因為當時的網絡速度對比現在來說慢了幾百倍,網絡速度跟不上我們的需要。在在典型的MapReduce部署中計算和存儲都在同一個集群中進行,比如后續的hadoop。這里其實也就是用本地IO速度來替換網絡傳輸速度。
隨着技術的進步,我們的網絡速度也越來越快,我們的瓶頸不再是網絡速度,但是我們的磁盤I/O速度卻沒有明顯的速度增長,計算和存儲融合的架構缺點也再逐漸暴露:
-
機器的浪費:業務是計算先達到瓶頸的,還是存儲先達到瓶頸的。這兩種情況往往是不一樣的,往往時間點也是不一樣的。在架構里就存在一定的浪費。如果說計算不夠,也是加一台機器;存儲不夠,還是加一台機器。所以這里就會存在很多浪費。
-
機器配比需要頻繁更新:一般來說在一個公司內機器的配型比較固定比如提供好幾種多少核,多少內存,多少存儲空間等等。但是由於業務在不斷的發展,那么我們的機器配型也需要不斷的更新。
-
擴展不容易:如果我們存儲不夠了通常需要擴展,計算和存儲耦合的模式下如果擴展就需要存在遷移大量數據。
由於計算和存儲耦合的缺點越來越多,並且網絡速度越來越快,現在架構又在重新向計算和存儲分離這一方向重新開始發展。
4.誰在使用計算和存儲分離
上面我們講了很多理論相關的知識,相信大家已經對“計算和存儲分離”已經有一定的認識了,那么其到底在哪些地方做了使用呢?其影響比較大的有兩塊,一個是數據庫,另外一個是消息隊列,接下來我會具體講下這兩塊到底是怎么利用“計算和存儲分離”的。
4.1 數據庫
一談到數據庫我們不得不想到MySql,這個應該也是大家最熟悉的數據庫,下面是Mysql的一個主從架構圖:
可以看見我們的master接收數據的變更,我們的從數據庫讀取binlog信息,重放binlog從而達到數據復制。
在Mysql的主從架構中有很多問題:
-
主庫的寫入壓力比較大的時候,主從復制的延遲會變得比較高,由於我們其復制的是binlog,他會走完所有的事務。
-
增加從節點速度慢,由於我們需要將數據全量的復制到從節點,如果主節點此時存量的數據已經很多,那么擴展一個從節點速度就會很慢高。
-
對於數據量比較大的數據庫,備份的速度很慢。
-
成本變高,如果我們的數據庫的容量比較大,那么我們相應的所有從節點的容量都需要和豬數據庫一樣大,我們的成本將會隨着我們所需要從數據庫的數量進行線性增加。
這一切的問題好像都在指引着我們走向計算和存儲分離的道路,讓所有的節點都共享一個存儲。在2014年,在AWS大會上,AWS就宣布推出Aurora。這是一個面向亞馬遜關系數據庫服務(RDS)的兼容MySQL的數據庫引擎,Aurora完美契合了企業級數據庫系統對高可用性、性能和擴展性、雲服務托管的需求。目前的Aurora可跨3個可用區的6-路復制、30秒內便可完成故障轉移、同時具備快速的crash recovery能力。在性能方面,Aurora現在比RDS MySQL5.6和5.7版本快5倍。
Aurora將MySQL存儲層變為為獨立的存儲節點,在Aurora中認為日志即數據,將日志徹底從Mysql計算節點中抽離出來,都由存儲節點進行保存,並且也取消了undolog用於減小計算存儲之間的交互和傳輸數據帶寬。
同樣的在阿里的團隊中,也借鑒了Aurora的思想,並在其上面做了很多優化,由於Aurora對於Mysql-Innodb的存儲引擎修改較大,后續的Mysql的更新,必然成本很大,所以阿里的團隊在保有了原有的MySQL IO路徑的基礎之上推出了PolarDB。其設計架構圖如下:
-
libfis:這是一個文件系統庫,提供了供計算節點訪問底層存儲的API接口,進行文件讀寫和元數據更新等操作,有了這個之后計算節點就不需要關心存儲的數據到底在哪。
-
ChunkServer可以認為是一個獨立的存儲子節點,每個ChunkServer管理着一塊SSD硬盤,多個ChunkServer組成Polardb存儲節點,對於計算節點來說只需要認為其是一個大的存儲節點就好。
-
PolarSwitch:是部署在計算節點的Daemon,它負責接收libpfs發送而來的文件IO請求,PolarSwitch將其划分為對應的一到多個Chunk,並將請求發往Chunk所屬的ChunkServer完成訪問。
當然PolarDB還有很多其他的細節,大家有興趣可以閱讀阿里雲的官方文檔,通過這種共享存儲的方式,我們就可以根據自己的業務來進行不同的配置申請,比如我們的對並發要求不高,對數據量要求很大,那么我們就可以申請大量的存儲空間,計算資源相對來說就可以較小,如果我們對並發要求很高,尤其是讀請求,那么我們就可以申請多台讀機器直到滿足我們要求為止。
其實不止是這些,現在很多的數據庫都在逐漸向“計算和存儲分離”靠攏,包括現在的OceanBase
,TiDB等等。所以“計算和存儲分離”應該是未來數據庫的主要發展方向。
4.2 消息隊列
我在之前寫過很多關於消息隊列的文章,有Kafka的,也有RocketMQ的,不論是Kafka還是RocketMQ其設計思想都是利用本地機器的磁盤來進行保存消息隊列,這樣其實是有一定的弊端的:
-
數據有限,使用者兩個消息隊列的同學應該深有感觸,一般會服務器保存最近幾天的消息,這樣的目的是節約存儲空間,但是就會導致我們要追溯一些歷史數據的時候就會導致無法查詢。
-
擴展成本高,在數據庫中的弊端在這里同樣也會展現。
針對這些問題ApachePulsar出現了,pulsar最初由Yahoo開發,在18年的時候一舉將kafka連續兩年InfoWorld最佳開源數據平台獎奪了過來。
在Pulsar的架構中,數據計算和數據存儲是單獨的兩個結構:
-
數據計算也就是Broker,其作用和Kafka的Broker類似,用於負載均衡,處理consumer和producer等,如果業務上consumer和producer特別的多,我們可以單獨擴展這一層。
-
數據存儲也就是Bookie,pulsar使用了Apache Bookkeeper存儲系統,並沒有過多的關心存儲細節,這一點其實我們也可以借鑒參考,當設計這樣的一個系統的時候,計算服務的細節我們需要自己多去思考設計,而存儲系統可以使用比較成熟的開源方案。
Pulsar理論上來說存儲是無限的,我們的消息可以永久保存,有人會說難道硬盤不要錢嗎?當然不是我們依然要錢,在Pulsar可以進行分層存儲,我們將舊的消息移到便宜的存儲方案中,比如AWS的s3存儲,而我們當前最新的消息依然在我們比較貴的SSD上。在這個模式下不僅是存儲是無限,我們的計算資源擴展也是無限的,因為我們的計算資源基本上是無狀態的,擴展是沒有任何成本的,所以Pulsar也搞出了一個多租戶的功能,而不用每個團隊單獨去建立一個集群,之前在美團的確也是這樣的,比較重要的BG基本上都有自己的Mafka集群,防止互相影響。
Kafka最新的一些提議,也在向這些方面靠攏,比如也在討論是否支持分層存儲,當然是否采用“計算和存儲分離”架構這個也是不一定的,但是我認為“計算和存儲分離”的方向也是消息隊列未來發展的主要方向。