從 Shard 到 Sharding
“Shard”這個詞英文的意思是“片段”,而作為資料庫相關的技術用語,似乎最早見於大型多人線上角色扮演遊戲(MMORPG)中的“Sharding” 姑且稱之為“分區”。
Sharding 不是一門新技術,而是一個相對簡樸的軟體理念。如您所知,MySQL 5 之後才有了資料表資料分割函數,那麼在此之前,很多 MySQL 的潛在使用者都對 MySQL 的擴充性有所顧慮,而是否具備資料分割函數就成了衡量一個資料庫可擴充性與否的一個關鍵計量(當然不是唯一指標)。資料庫擴充性是一個永恒的話題,MySQL 的推廣者經常會被問到:如在單一資料庫上處理應用資料捉襟見肘而需要進行分區化之類的處理,是如何辦到的呢? 答案是:Sharding。
Sharding 不是一個某個特定資料庫軟體附屬的功能,而是在具體技術細節之上的抽象處理,是水平擴充(Scale Out,亦或橫向擴充、向外擴充)的解決方案,其主要目的是為突破單節點資料庫伺服器的 I/O 能力限制,解決資料庫擴充性問題。
事關資料庫擴充性
說起資料庫擴充性,這是個非常大的話題。目前的商業資料都有自己的擴充性解決方案,在過去相對來說比較成熟,但是隨著互連網的高速發展,不可避免的會帶來一些計算模式上的演變,這樣很多主流商業系統也難免暴露出一些不足之處。比如 Oracle 的 RAC 是採用共用儲存機制,對於 I/O 密集型的應用,瓶頸很容易落在儲存上,這樣的機制決定後續擴容只能是 Scale Up向上擴充) 類型,對於硬體成本、開發人員的要求、維護成本都相對比較高。
Sharding 基本上是針對開來源資料庫的擴充性解決方案,很少有聽說商務資料庫進行 Sharding 的。目前業界的趨勢基本上是擁抱 Scale Out,逐漸從 Scale Up 中解放出來。
Sharding 的應用情境
任何技術都是在合適的場合下能發揮應有的作用。 Sharding 也一樣。聯機遊戲、IM、BSP 都是比較適合 Sharding 的應用情境。其共性是抽象出來的資料對象之間的關聯資料很小。比如IM,每個使用者如果抽象成一個資料對象,完全可以隔離儲存區 (Isolated Storage)在任何一個地方,資料對象是 Share Nothing 的;再比如 Blog 服務提供者的網站內容,基本為使用者產生內容(UGC),完全可以把不同的使用者隔離到不同的儲存集合,而對使用者來說是透明的。
這個 “Share Nothing”是從資料庫叢集中借用的概念,舉例來說,有些類型的資料粒度之間就不是 "Share Nothing" 的,比如類似交易記錄的曆史表資訊,如果一條記錄中既包含賣家資訊與買家資訊,如果隨著時間推移,買、賣家會分別與其他使用者繼續進行交易,這樣不可避免的兩個買賣家的資訊會分布到不同的 Sharding DB 上,而這時如果針對買賣家查詢,就會跨越更多的 Sharding ,開銷就會比較大。
Sharding 並不是資料庫擴充方案的銀彈,也有其不適合的情境,比如處理事務型的應用就會非常複雜。對於跨不同DB的事務,很難保證完整性,得不償失。所以,採用什麼樣的 Sharding 形式,不是生搬硬套的。
Sharding與資料庫分區(Partition)的區別
有的時候,Sharding 也被近似等同於水平資料分割(Horizontal Partitioning),網上很多地方也用水平資料分割來指代 Sharding,但我個人認為二者之間實際上還是有區別的。的確,Sharding 的思想是從分區的思想而來,但資料庫分區基本上是資料對象層級的處理,比如表和索引的分區,每個子資料集上能夠有不同的實體儲存體屬性,還是單個資料庫範圍內的操作,而 Sharding 是能夠跨資料庫,甚至跨越物理機器的。