先來說兩個DBA經常遇到的場景。
場景1:有兩個分布在不同實例的多張不通的表,想要通過某字段關聯做統計,或者想將分布在不同實例的表合并到一個實例中做查詢。
場景2:由于數據庫容量瓶頸或數據庫訪問性能瓶頸,將某大庫、大表或訪問量大的表進行拆分,再分布到不同實例中。
這兩種場景覆蓋了垂直拆分和水平拆分,筆者想到的解決辦法可能有使用數據庫中間件,使用MySQL分區表,使用Galera Cluster for MySQL,使 用 MySQL的 多源復制,使用federated,使用MySQL Sharding和Spider。本文就是基于Spider的分布式數據庫解決方案,下面詳細介紹一下。

圖1 spider架構圖

圖2 垂直分表場景圖

圖3 水平分表場景圖
Spider引擎是一個內置的支持數據分片特性的存儲引擎,支持分區和XA事務,該引擎可以在服務器上建立和遠程服務器表之間的鏈接,操作起來就像操作本地的表一樣。并且后端可以是任何的存儲引擎。
Spider引擎根據表的設置的規則以及Server表的規則自動進行智能路由,實現對后端數據庫不通的表或者數據分片的訪問和修改。因此該引擎對業務是完全透明的。
目前Spider引擎已經集成到了MariaDB中,安裝使用非常方面,目前最新的版本是Spider 3.2.37。更多信息可以訪 問 :https://mariadb.com/kb/en/mariadb/spider-storage-engineoverview/。
Spider架構圖如圖1。
如圖2所示,Spider后面接4臺DB Server,可將不同功能的表分布到后端不同的DB Server中,比如user_info的表專門存放在HostA中,user_msg表 存 放 在HostB中,user_detail表存 放 在 HostC中,user_log表存放在HostD中。
當我們執行HostA的SQL的時候,Spider會通過user_info表的映射關系以及HostA的IP映射關系,將查詢user_info表的請求都轉發到HostA上,HostA查詢完成后再將結果發給Spider服務器,Spider再轉發給客戶端。
Spider支持多種水平分表的模式,目前支持hash分表(hash)、范圍分表(range)、列表分表(list),筆者用range來說明水平分表的工作原理。
如 圖3所 示,Spider對user_info表 針 對id進行了分區,將0~100000的記錄存儲在了HostA,100000~200000的記錄存儲在 了 HostB,200000~300000的記錄存儲在了HostC,300000~400000的記錄存儲在了HostD。當用戶訪問user_info的某條或者多條記錄的時候,Spider會根據分區的情況,對相關的記錄落在某臺或者多臺DB Server上,再進行轉發。比 如select*from user_info where id=1這個SQL,Spider在收到這個請求后,會跟進分區情況選擇對應的DB Server進行轉發。這里會將該請求轉發到HostA中。HostA處理完成后,再將結果返回給Spider Server,Spider再將結果轉發給發起請求的客戶端。

圖4 安裝成功

圖5 部署拓撲圖
從Spider 10.0.0.4版本開始,Spider引擎就集成到了MariaDB中,集成后安裝就非常的簡單,安裝步驟如下:
安裝方法非常簡單,這里不在贅述,具體可以參考:https://mariadb.com/kb/en/mariadb/getting-installingand-upgrading-mariadb/
mysql -uroot -p <install_spider.sql
或者登錄MySQL后執行
source /path/install_spider.sql
備 注 :install_spider.sql在share目錄下面。
這個命令所做的事情如下:
創建Spider相關的系統表

創建Spider相關的表結構,加載Spider引擎
如果出現圖4所示的結果就說明已經支持了Spider引擎。
本實踐環境基于tspider-1.8.5環境全部驗證通過。
在實戰部分,筆者使用了2臺DB Server,部署圖如圖5所示。
首先,創建Spider Server訪問后端DB Server的權限(后面配置中需要用到)。
grantallon*.* tospider_d b_all@'10.128.128.91'identified by 'tospider_db_all';
其次,創建Spider后端DB Server的配置??梢酝ㄟ^執行如下SQL的形式直接創建。
createserver backend1 foreign data wrapper mysql options(host '10.128.128.60',database 'test', user'spider_db_all', password'spider_db_all', port 3306);
createserver backend2 foreign data wrapper mysql options(host '10.128.128.88',database'test',user'spider_db_all',password'spider_db_all',port 3306);

圖6 查詢mysql.servers表
也可以通過直接給mysql.servers表中直接插入相關的記錄,不過后面執行flush hosts才能生效。
insert into mysql.servers(Server_name,Host,Db,Username,Password,Po rt,Socket,Wrapper,Owner)values('backend1','10.1 28.128.60','test','spid er_db_all','spider_db_al l',3306,'','mysql','');
insert into mysql.servers(Server_name,Host,Db,Username,Password,Po rt,Socket,Wrapper,Owner)values ('backend2','10.1 28.128.88','test','spid er_db_all','spider_db_al l',3306,'','mysql','');
創建完成后可以直接查詢mysql.servers表,確認是否添加成功,如圖6所示。
然后,創建基礎測試表。
在后端兩臺DB Server上創建基礎測試表(在60和88上執行)。

首先,建立垂直表(遠程表進行測試)。

創建之后,執行對應增刪改查,看看是否對應的操作都發生在了backend1對應的DB Server上。
測試完成后,刪除掉Spider 服務器上的test_spider表,你會發現drop掉Spider上的表,不會導致后端DB Server上的表被刪除。
其次,建立hash分區表。

創建之后,執行對應增刪改查,看看是否對應的操作都發生在了backend1和backend2對應的DB Server上。
測試完成后,刪除掉Spider服務器上的test_spider表,你會發現drop掉Spider上的表,不會導致后端DB Server上的表被刪除。
然后,建立range分區表。

創建之后,執行對應增刪改查,看看是否對應的操作都發生在了backend1和backend2對應的DB Server上。
測試完成后,刪除掉Spider服務器上的test_spider表,你會發現drop掉Spider上的表,不會導致后端DB Server上的表被刪除。
最后,建立list分區表測試。

創建之后,執行對應增刪改查,看看是否對應的操作都發生在了backend1和backend2對應的DB Server上。
測試完成以后,刪除掉Spider 服務器上的test_spider表,那么你會發現drop掉Spider上的表,不會導致后端DB Server上的表被刪除。