DB 分庫分表(3):關於使用框架還是自主開發以及 sharding 實現層面的考量

發表於2017-07-17

當團隊對系統業務和資料庫進行了細緻的梳理,確定了切分方案後,接下來的問題就是如何去實現切分方案了,目前在sharding方面有不少的開源框架和產品可供參考,同時很多團隊也會選擇自主開發實現,而不管是選擇框架還是自主開發,都會面臨一個在哪一層上實現sharding邏輯的問題,本文會對這一系列的問題逐一進行分析和考量。
一、sharding邏輯的實現層面

從一個系統的程式架構層面來看,sharding邏輯可以在DAO層、JDBC API層、介於DAO與JDBC之間的Spring資料訪問封裝層(各種spring的template)以及介於應用伺服器與資料庫之間的sharding代理伺服器四個層面上實現。

圖1. Sharding實現層面與相關框架/產品

  • 在DAO層實現

當團隊決定自行實現sharding的時候,DAO層可能是嵌入sharding邏輯的首選位置,因為在這個層面上,每一個DAO的方法都明確地知道需要訪問的資料表以及查詢引數,藉助這些資訊可以直接定位到目標shard上,而不必像框架那樣需要對SQL進行解析然後再依據配置的規則進行路由。另一個優勢是不會受ORM框架的制約。由於現在的大多數應用在資料訪問層上會依賴某種ORM框架,而多數的shrading框架往往無法支援或只能支援一種orm框架,這使得在選擇和應用框架時受到了很大的制約,而自行實現sharding完全沒有這方面的問題,甚至不同的shard使用不同的orm框架都可以在一起協調工作。比如現在的java應用大多使用hibernate,但是當下還沒有非常令人滿意的基於hibernate的sharding框架,(關於hibernate hards會在下文介紹),因此很多團隊會選擇自行實現sharding。

簡單總結一下,在DAO層自行實現sharding的優勢在於:不受ORM框架的制約、實現起來較為簡單、易於根據系統特點進行靈活的定製、無需SQL解析和路由規則匹配,效能上表現會稍好一些;劣勢在於:有一定的技術門檻,工作量比依靠框架實現要大(反過來看,框架會有學習成本)、不通用,只能在特定系統裡工作。當然,在DAO層同樣可以通過XML配置或是註解將sharding邏輯抽離到“外部”,形成一套通用的框架. 不過目前還沒有出現此類的框架。

  • 在ORM框架層實現

在ORM框架層實現sharding有兩個方向,一個是在實現O-R Mapping的前提下同時提供sharding支援,從而定位為一種分散式的資料訪問框架,這一類型別的框架代表就是guzz另一個方向是通過對既有ORM框架進行修改增強來加入sharding機制。此型別的代表產品是hibernate shard. 應該說以hibernate這樣主流的地位,行業對於一款面向hibernate的sharding框架的需求是非常迫切的,但是就目前的hibernate shards來看,表現還算不上令人滿意,主要是它對使用hibernate的限制過多,比如它對HQL的支援就非常有限。在mybatis方面,目前還沒有成熟的相關框架產生。有人提出利用mybatis的外掛機制實現sharding,但是遺憾的是,mybatis的外掛機制控制不到多資料來源的連線層面,另一方面,離開外掛層又失去了對sql進行集中解析和路由的機會,因此在mybatis框架上,目前還沒有可供借鑑的框架,團隊可能要在DAO層或Spring模板類上下功夫了。

  • 在JDBC API層實現

JDBC API層是很多人都會想到的一個實現sharding的絕佳場所,如果我們能提供一個實現了sharding邏輯的JDBC API實現,那麼sharding對於整個應用程式來說就是完全透明的,而這樣的實現可以直接作為通用的sharding產品了。但是這種方案的技術門檻和工作量顯然不是一般團隊能做得來的,因此基本上沒有團隊會在這一層面上實現sharding,甚至也沒有此類的開源產品。筆者知道的只有一款商業產品dbShards採用的是這一方案。

  • 在介於DAO與JDBC之間的Spring資料訪問封裝層實現

在springd大行其道的今天,幾乎沒有哪個java平臺上構建的應用不使用spring,在DAO與JDBC之間,spring提供了各種template來管理資源的建立與釋放以及與事務的同步,大多數基於spring的應用都會使用template類做為資料訪問的入口,這給了我們另一個嵌入sharding邏輯的機會,就是通過提供一個嵌入了sharding邏輯的template類來完成sharding工作.這一方案在效果上與基於JDBC API實現的方案基本一致,同樣是對上層程式碼透明,在進行sharding改造時可以平滑地過度,但它的實現卻比基於JDBC API的方式簡單,因此成為了不少框架的選擇,阿里集團研究院開源的Cobar Client就是這類方案的一種實現。

  • 在應用伺服器與資料庫之間通過代理實現

在應用伺服器與資料庫之間加入一個代理,應用程式向資料發出的資料請求會先通過代理,代理會根據配置的路由規則,對SQL進行解析後路由到目標shard,因為這種方案對應用程式完全透明,通用性好,所以成為了很多sharding產品的選擇。在這方面較為知名的產品是mysql官方的代理工具:Mysql Proxy和一款國人開發的產品:amoeba。mysql proxy本身並沒有實現任何sharding邏輯,它只是作為一種面向mysql資料庫的代理,給開發人員提供了一個嵌入sharding邏輯的場所,它使用lua作為程式語言,這對很多團隊來說是需要考慮的一個問題。amoeba則是專門實現讀寫分離與sharding的代理產品,它使用非常簡單,不使用任何程式語言,只需要通過xml進行配置。不過amoeba不支援事務(從應用程式發出的包含事務資訊的請求到達amoeba時,事務資訊會被抹去,因此,即使是單點資料訪問也不會有事務存在)一直是個硬傷。當然,這要看產品的定位和設計理念,我們只能說對於那些對事務要求非常高的系統,amoeba是不適合的。

二、使用框架還是自主開發?

前面的討論中已經羅列了很多開源框架與產品,這裡再整理一下:基於代理方式的有MySQL Proxy和Amoeba,基於Hibernate框架的是Hibernate Shards,通過重寫spring的ibatis template類是Cobar Client,這些框架各有各的優勢與短板,架構師可以在深入調研之後結合專案的實際情況進行選擇,但是總的來說,我個人對於框架的選擇是持謹慎態度的。一方面多數框架缺乏成功案例的驗證,其成熟性與穩定性值得懷疑。另一方面,一些從成功商業產品開源出框架(如阿里和淘寶的一些開源專案)是否適合你的專案是需要架構師深入調研分析的。當然,最終的選擇一定是基於專案特點、團隊狀況、技術門檻和學習成本等綜合因素考量確定的。

相關文章