聊聊計算和存儲分離
1. 背景
這篇文章是我一直想寫的一篇,因爲 “計算和存儲分離” 最近幾年在大家的視野中出現得越來越多,但其實很多對於其到底代表着什麼也是模糊不清,這裏我查閱了很多的資料再結合平時自己的理解,聊聊到底什麼是“計算和存儲分離”
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 最新的一些提議,也在向這些方面靠攏,比如也在討論是否支持分層存儲,當然是否採用 “計算和存儲分離” 架構這個也是不一定的,但是我認爲 “計算和存儲分離” 的方向也是消息隊列未來發展的主要方向。
總結
“計算和存儲分離” 隨着雲原生的發展,在各種系統中出現的次數越來越多,希望大家讀完這篇文章能對其有個簡單的認識。同時如果大家未來在設計系統的時候,這個方案也可以作爲選擇方案之一進行考慮。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/WeZYx9KJU6EA0rEVpcGYTg