1. 程式人生 > >林尚泉:“小米結構化儲存系統及融合雲平臺的設計與實踐” – 運維派

林尚泉:“小米結構化儲存系統及融合雲平臺的設計與實踐” – 運維派

由工業和資訊化部指導,中國資訊通訊研究院主辦,業界知名組織雲端計算開源產業聯盟(OSCAR)承辦的2017全球雲端計算開源大會於4月19日-20日在北京國家會議中心順利召開。本文為本屆大會嘉賓分享的大會演講速記內容,敬請瀏覽。

嘉賓介紹:林尚泉

公司職務:小米科技開發工程師

大會演講速記

小米

我是來自小米的雲平臺的工程師林尚泉,下面我來給大家介紹一下小米結構化儲存系統以及融合雲平臺的設計和實踐。

大綱

這個是今天的演講大綱,比較簡單。

NoSQL資料庫

結構化儲存是一個分散式NoSQL資料庫服務,對標AWS DynamoDB,我們的目標是要把它做成一個彈性可擴充套件、高可用、低延時、穩定可靠的資料庫服務。

首先介紹一下專案的背景,HBase在小米用的比較好,但是用著就發現了一些問題,包括一些認證和環境配置比較複雜,還有多語言支援的不太好等等,到後面我們還要支援生態鏈公司的一些結構化資料的儲存需求,所以我們需要在公網裡面提供訪問。

儲存

HBase在公網直接提供訪問也不大方便,所以我們就做了這套服務,它是基於HBase的,對外提供無狀態的公網訪問,簡化了客戶的配置,支援多種主流語言的SDK,因為一個叢集供多個使用者一起使用,所以需要支援多租戶的功能,包括訪問控制和流量控制,並且我們還在原生的HBase上做了一些功能擴充套件,因為原生的HBase是隻支援按主鍵索引,沒有二級索引,也沒有資料型別的概念。

儲存

我們在上面做了一些功能擴充套件,包括資料型別、二級索引、stream、還有軟刪除和資料冷備等等這些功能。現在這個服務不僅支援了小米內部業務,包括MIUI、小米網等等,還支援了十幾家生態鏈公司的結構化儲存的業務。

看一下應用規模,我們在北京天津美國新加坡都有相應的叢集,機器規模一百多臺,支援的業務數二十幾個,資料量一百多TB還有數千億行,看起來不是很多,但是前段時間統計,現在的資料量是以每兩個月翻倍的在增長,現在單叢集的QPS大概是幾十萬級別。

這是結構化儲存一個典型的部署,分為主備結構、底層是Zookeeper/HDFS/HBase等系統,主叢集使用ssd盤,備叢集使用hdd盤,在HBase上面那層我們封了一層libsds,主要對HBase做了一些功能擴充套件,在libsds庫上,我們是直接對外提供服務的ThriftServer,使用Thrift 的RPC框架,支援多種語言的SDK,還有流量控制等功能。主叢集是直接供使用者的線上訪問,備叢集除了充當主叢集的熱備之外還會給使用者跑一些離線作業。

libsds庫

下面首先介紹一下libsds庫,主要在HBase上做了以下的功能擴充套件,一個是規範化的資料模型,還有一些資料型別的支援,還有區域性二級索引以及全域性二級索引,下面分別介紹一下幾個功能,規範化的資料模型意思是在libsds那層,表是有schema的,

這個圖就是對應HBase的一個KeyValue,還支援了多種資料型別,包括各種基本型別和集合型別。

編碼

我們採用了HBase8201和SQLite編碼方案對RowKey進行編碼,保證跟原來的資料型別的順序是一致的,還可以支援逆序。

索引

區域性二級索引,這種二級索引是實體組內部的索引,索引資料是和原資料存在同一張表上的不同Column Family,我們實現了個基於正則表示式的字首分割策略,確認保證同一個實體組鍵裡面的資料是在同一個Hbase region上面,並且不能被split的,這兩個圖剛才介紹過,一個是原資料的,我們建了局部索引,除了寫原資料還會加一行索引資料,就是下面這個圖。

RowKey的排列是實體組鍵到索引鍵再到主鍵,可以看到原資料和索引資料的實體組鍵是一樣的,然後根據我們實現的字首分割策略就可以保證原資料和索引資料在同一臺機器上,就可以比較簡單的去保證這兩個資料寫入的原子性。

我們是通過HBase Coprocessor來實現了indexObserver,也就是客戶傳送Put或Delete請求後我們會攔截這個操作,然後再計算要上出來索引,再把它放到原來的資料裡,最後再同一臺機器上一起落地,就可以保證原資料和索引資料的原子性。

還支援了多種型別的區域性二級索引,其中包括EAGER型別,也就是更新刪除時同時刪除失效索引,是適合寫少讀多的場景,而LAZY索引是讀取判斷索引有效性,更新時不做額外操作,適合寫多讀少,還有IMMUTABLE是需要使用者保證資料的只讀性,就適合以只讀資料的一次性寫入,讀寫都不需要做額外的判斷,這種比較高效。

還支援了全域性二級索引,和區域性二級索引不一樣的地方是它的索引資料是單獨的存在一個HBase表裡,我們採用了谷歌的percolator方案實現的,我們在hbase上實現了這套演算法叫Themis,這個已經開源,這個演算法可以保證跨表更新的原子性,Chronos為全域性單調遞增時間戳。

全域性二級索引資料對應的HBase的KeyValue跟區域性二級索引不大一樣,是以索引鍵排在最前面,再到實體組鍵和主鍵,我們對區域性二級索引和全域性二級索引做了一下效能對比。這個圖是對某一張表建立了一個全域性二級索引和區域性二級索引,然後再寫,紅色是區域性二級索引,藍色是全域性二級索引

可以看到因為全域性二級索引會涉及到分散式的事務,可以看到效能損耗比較大,區域性二級索引比它有好個四倍左右,而讀的話同樣區域性二級索引好個兩倍。

另外我們實現了stream功能,如果開了這個功能,使用者對錶的修改除了在原來的資料CF上寫,還會封裝成一條訊息在另一個CF裡再寫一份,另外起一個MR job定期掃那個額外的CF,再把那個訊息打到流式訊息佇列裡,使用者就會拿到流式訊息佇列來消費這些資料。

其中包括兩種型別,一個是RECORD IMAGE,得到的訊息是這行資料被修改以後最後的檢視,使用者拿著這種型別的訊息就可以做一些最終一致的增量備份,另外是MUTATE LOG,就是每一行的修改日誌,這種型別再結合一個定期打快照的功能,就可以把指定某一個表恢復到歷史任意一個時間點。

我們採用了facebook 的Thrift框架,對外遮蔽了一些複雜的配置,由於是使用了Thrift框架,很方便的可以支援多種語言的SDK。

ThriftServer主要對外提供一個無公網的http服務,對外遮蔽了HBase,使用者只需要拿到一個域名就可以直接訪問,簡化了認證和配置,支援了多種語言的SDK,多租戶包括訪問控制和流量控制。

ACL功能,我們是在HBase那裡存了一份元資料表,它的格式是某一個表有哪些ACL資訊,並且每一個節點會對元資料做本地快取,假如有使用者發了一個修改ACL的請求,這個ThriftServer不僅要更新元資料表,還要在Zookeeper修改一個節點,因為所有的ThriftServer節點都監聽了Zookeeper的那個節點,就會收到一個通知進行更新,通過訪問元資料表更新本地快取。

流量控制,SDS支援使用者每一個表進行預設定的讀寫配額,設定讀寫配額的時候SDS會檢查一下叢集的能力,叢集的能力是根據我們的一些效能測試得到的,做限流的時候是基於token bucket演算法進行限流的,叢集能力使用到80%的時候會提醒我們進行叢集擴容。還實現了軟刪除的功能,因為要保證資料安全,

軟刪除就是使用者發一個刪表請求,要刪除一張表的時候,SDS後臺會先對這個表打一個快照,然後再去刪除這個表,這個時候會存一堆snapshot檔案,在經過TTL 的時間後刪除,在刪除之前使用者可以通過restoretable通過clonesnapshot把表恢復出來。

而資料冷備我們實現了一個工具,是可以把HBase一些snapshot推到AWS S3,需要的時候再拉下來。結構化資料儲存系統暫時介紹到這裡。

我們來看一下融合雲平臺。這個是小米融合雲平臺的控制檯的首頁,可以看到它除了剛才介紹的結構化儲存之外,還包括的檔案儲存,團隊管理,流式訊息佇列和深度學習等等的一些服務,我們的願景是把它打造成一個閉環的集計算和儲存於一體的雲服務平臺,更好的給小米的使用者和生態鏈公司進行服務。然後使用者要訪問上面的任何一個服務都要通過團隊管理,自己去申請一些team等等。

這個是我們融合雲平臺的架構圖,中間主要的服務是Zookeeper、HDFS、HBase等等服務,在上面有SDS、FDS、EMQ,還有其他服務等等,外圍有一些公用的元件就是部署服務,我們為了方便我們叢集的管理還有一些升級部署,我們開發了一套公用的部署系統,所有的部署都是通過融合雲的部署系統。

還有一套公用的報警系統,並且使用者訪問的時候都要通過團隊認證管理提供一個統一的認證入口。下面來簡單介紹一下三模組,融合雲通過一個CloudManager進行了團隊認證管理,使用者可以對CloudManager發一些團隊管理請求,新增或刪除team等,這個模組就會把這些資訊存在MySql,比如使用者要訪問我們的結構化儲存或者檔案儲存的服務,如果前端過來的請求,前端首先會把這個請求轉發到CloudManager這個模組,CloudManager經過驗證以後會從MySQL讀出團隊資訊,再放到http header裡面再轉發到後端service。

如果通過SDK直接訪問service,要通過簽名進行認證才的,具體是service調CloudManager的RestfulAPI,這個Restful API會返回使用者的團隊資訊,service再把這個解密,算一個簽名出來,再做對比。

融合雲的部署系統是使用了我們小米發的Minos2.0,1.0已經開源,2.0實際上是在1.0的基礎上增加了一些認證授權的模組,主要包括Tank管理伺服器,叢集每一個節點都用supervisor監控,提供了工具來給使用者做叢集的升級等等,這些操作都需要經過CloudManager進行認證,主要是為了保證只有叢集的owner或者對這個叢集有相應的許可權的使用者才可以進行相應的操作。

提供了一套統一的監控告警系統,小米其實在運維團隊也開發了一套open-falcon的告警系統,為什麼自己還要再搞一套?因為那套在公網訪問是不太方便,因為我們這一套系統需要供很多的使用者一起用,需要資料隔離,並且那套是使用RRD來儲存資料,不儲存原始資料,我們的很多使用者是有這個需求的。更重要的一個原因就是我們需要為使用者來監控其他服務的資源上面的一些指標提供一個統一的入口,例如使用者用了結構化儲存還有檔案儲存等等,這些服務上面的資源的指標都可以通過我們統一的監控告警系統來進行統一的監控。

它的主要架構是這樣的,使用者是可以直接往我們的監控告警系統的ThriftServer發請求,包括兩種,一個是推送指標或者查詢指標,這種請求在ThriftServer直接轉發到OpenTSDB,再對這些指標進行儲存,OpenTSDB支援資料的下采樣和聚合。

另外一種就是對指標監控要定製一些告警規則,使用者可以把這個告警規則的請求發到service,ThriftServer把這個規則存到SDS,告警使用者模組是對使用者每一個指標都要過一遍,根據使用者定製的告警規則看有沒有觸發告警,因為需要有一些指標的記憶體狀態,所以就需要保證同一個指標必須發到模組的同一個節點上。

另外還有一個Collector模組,把我們所有小米融合雲裡面的子服務的指標,就是使用者關注的指標統一收集然後推送到我們的監控告警系統給使用者做統一監控。我今天的分享就到這裡,謝謝。

文章來自微信公眾號:雲端計算開源產業聯盟