本篇為InfoQ中文站供稿
原文鏈接:
https://www.infoq.cn/article/NHSAAmN*MfpLiTiTTEu5?from=timeline&isappinstalled=0
ShardingSphere 是什么?
ShardingSphere 是一套開源的分布式數(shù)據(jù)庫中間件解決方案組成的生態(tài)圈,它由 Sharding-JDBC、Sharding-Proxy 和 Sharding-Sidecar(規(guī)劃中)這 3 款相互獨立的產(chǎn)品組成。他們均提供標(biāo)準(zhǔn)化的數(shù)據(jù)分片、分布式事務(wù)和數(shù)據(jù)庫治理功能,可適用于如 Java 同構(gòu)、異構(gòu)語言、容器、云原生等各種多樣化的應(yīng)用場景。ShardingShpere 在剛剛過去的雙十一之前通過了 Apache 基金會的投票,正式進(jìn)入孵化器,成為 Apache 的首個分布式數(shù)據(jù)庫中間件。
ShardingSphere 可以采用混合使用 Sharding-JDBC 和 Sharding-Proxy 的部署方式滿足在線 + 管理的能力,也可以獨立使用 Sharding-JDBC 或 Sharding-Proxy。ShardingSphere 希望可以通過多元化的接入端架構(gòu)去滿足不同需求。
Vitess 是什么?
Vitess源起于 Youtube,現(xiàn)已屬于 PlanetScale 的開源產(chǎn)品。它致力于部署、擴(kuò)展和管理大型 MySQL 實例集群的數(shù)據(jù)庫解決方案。它結(jié)合了許多重要的 MySQL 功能和 NoSQL 數(shù)據(jù)庫的可擴(kuò)展性,提供數(shù)據(jù)分片、分布式事務(wù)以及管理大量 MySQL 實例等功能。
Vitess 由負(fù)責(zé)元數(shù)據(jù)存儲的 Topology、負(fù)責(zé)應(yīng)用接入和 SQL 路由的 vtgate、負(fù)責(zé)重寫和執(zhí)行 SQL 的 vttablet 以及兩類管理工具 vtctl(用于命令行) 和 vtctld(用于圖形界面) 等服務(wù)組件共同構(gòu)成。用戶可以通過支持 MySQL 協(xié)議的客戶端,或使用 Vitess 的客戶端 API 使用 Vitess。
應(yīng)用功能對比
面對這兩個同樣優(yōu)秀的產(chǎn)品,用戶該在何種場景下選用哪款產(chǎn)品,想必有所糾結(jié)。本文接下來將使用 Vitess v2.2 和 ShardingSphere 3.0.0,從應(yīng)用功能和管理功能的角度,以官方文檔為基礎(chǔ),進(jìn)行測試對比,盡可能展示出兩者在已有功能和實現(xiàn)思路側(cè)重點上的不同。
接入方式
Vitess 通過組件 vtgate 作為中心化的接入代理,用戶可以通過 Vitess 的 gRPC 連接器或各類 MySQL 原生驅(qū)動進(jìn)行連接。Vitess 的 gRPC 連接器目前僅支持 Java 和 Go 兩種語言,若使用原生驅(qū)動則沒有語言限制,目前 Vitess 支持 MySQL 和 MariaDB 兩種數(shù)據(jù)庫。
ShardingSphere 提供 Proxy 和 JDBC 兩種接入方式,其中 Sharding-Proxy 和 vtgate 類似,提供了中心化的接入代理,用戶可以通過 MySQL 原生驅(qū)動進(jìn)行連接,理論上支持所有開發(fā)語言,目前同樣支持 MySQL 和 MariaDB 數(shù)據(jù)庫;Sharding-JDBC 可理解為增強版的 JDBC 驅(qū)動,提供無中心化的輕量級運行方式,讓客戶端直連數(shù)據(jù)庫,無網(wǎng)絡(luò)二次轉(zhuǎn)發(fā)的消耗。由于是 JDBC 的增強,因此沒有數(shù)據(jù)庫類型的限制,可以支持 MySQL、Oracle、SQLServer 和 PostgreSQL 等。
通過表格,可以更直觀的比較雙方的接入方式區(qū)別:
Vitess | Sharding-Proxy | Sharding-JDBC | |
---|---|---|---|
中心化 | 是 | 是 | 否 |
靜態(tài)入口 | 有 | 有 | 無 |
異構(gòu)語言 | 原生驅(qū)動任意 gRPC 僅 Java 和 Go | 任意 | 僅 Java |
數(shù)據(jù)庫 | MySQL 和 MariaDB | MySQL 和 MariaDB | 任意 |
分片模式
Vitess 在分片上采用了每個數(shù)據(jù)庫實例均創(chuàng)建一個分庫,并且不進(jìn)行分表的方式,即多實例單庫單表。由于 Vitess 的分片模式相對固定,因此在配置分片時通過 JSON 指定分片表、分片字段和分片算法,分片之后的庫名由 Vitess 自動管理,表名不變。
ShardingSphere 支持單獨分庫、單獨分表和同時分庫分表的分片方式,并且提供四種不同的分片策略以及能夠讓用戶自行實現(xiàn)分片算法,使得用戶能夠更加自由地控制數(shù)據(jù)分片。
單純描述有些抽象,接下來分別創(chuàng)建一個分片的例子進(jìn)行測試.
首先模仿 Vitess 官方文檔的測試用例,創(chuàng)建了一個名為 testkeyspace 的鍵空間(keyspaces),為其設(shè)置了 2 個分片。同時指定了 t_order 和 t_order_item 兩張分表,分別使用 user_id 和 order_id 進(jìn)行 Hash 分片。
在建表完畢后,通過 DataGrip 客戶端分別連接 vtgate 和實際 MySQL 實例進(jìn)行查看。
vtgate 執(zhí)行 show databases 和 show tables。
從 MySQL 實例的拓?fù)淇闯觯琕itess 在每一個分片數(shù)據(jù)庫實例中,都創(chuàng)建了一個 vt${keyspace_name}的庫,并且將建表語句廣播到所有數(shù)據(jù)庫執(zhí)行。
同樣模仿 ShardingSphere 的官方樣例,在 Sharding-Proxy 中配置 test_keyspace 分庫及 t_order,t_order_item 兩張分表。為了區(qū)別 ShardingSphere 和 Vitess 的分片能力,這里選用同時分庫分表的方式進(jìn)行分片,通過 user_id 取余進(jìn)行分庫、order_id 取余進(jìn)行分表。
在進(jìn)行配置的時候,可以利用 InlineShardingStrategy 直接使用 Groovy 表達(dá)式簡化配置,如本例中可簡化配置為:
test_keyspace_${user_id % 2}
t_order_${order_id % 2}
t_order_item_${order_id % 2}
在建表完畢后,通過 DataGrip 客戶端分別連接 Sharding-Proxy 和實際 MySQL 實例進(jìn)行查看。
Sharding-Proxy 執(zhí)行 show databases 和 show tables:
)
MySQL 實例中的拓?fù)浣Y(jié)構(gòu):
同樣通過表格,直觀的展示兩者分片上的區(qū)別:
Vitess | ShardingSphere | |
---|---|---|
分庫 | 支持 | 支持 |
分表 | 不支持 | 支持 |
分庫 + 分表 | 不支持 | 支持 |
配置方式 | JSON | Groovy 或?qū)崿F(xiàn)接口 |
多 Schema 切換 | 支持 | 支持 |
由此可見,ShardingSphere 和 Vitess 在分片模式上有著很大的區(qū)別,ShardingSphere 具有更豐富更自由的分片方式,能夠應(yīng)付更多的應(yīng)用場景。
SQL 支持
由于 SQL 語法靈活復(fù)雜,分布式數(shù)據(jù)庫和單機數(shù)據(jù)庫的查詢場景又不完全相同,難免有和單機數(shù)據(jù)庫不兼容的 SQL 出現(xiàn)。針對該問題,Vitess 和 ShardingSphere 都在官方文檔中進(jìn)行了說明。
在 ShardingSphere 中,對于已支持和未支持的 SQL 種類作出了明確的標(biāo)注,對于常用的分頁、排序、分組、聚合都進(jìn)行了支持,并支持部分關(guān)聯(lián)查詢,具體內(nèi)容可以通過官方文檔 使用規(guī)范 > SQL 中進(jìn)行查閱。
而 Vitess 暫時沒有明確的文檔標(biāo)明已支持和未支持的 SQL 種類,只在 FAQ 中的test-case標(biāo)注了當(dāng)前已經(jīng)出現(xiàn)的未支持的 SQL 的情況。
為了更直觀地展示兩者 SQL 支持情況,這里選取了一部分常用的 SQL 類型,根據(jù)文檔說明并結(jié)合實際測試結(jié)果,列出參考列表:
SQL 類型 | 測試 SQL | Vitess | ShardingSphere |
---|---|---|---|
全表查詢 | SELECT * FROM t_order; | 支持 | 支持 |
等值查詢 |
SELECT FROM t_order WHERE user_id = 7; SELECT FROM t_order WHERE user_id = 7 and order_id=9; |
支持 | 支持 |
范圍查詢 |
SELECT FROM t_order WHERE user_id in (7, 9); SELECT FROM t_order WHERE user_id BETWEEN 7 AND 10; SELECT FROM t_order WHERE user_id=7 or user_id=11; SELECT FROM t_order WHERE user_id > 1; |
支持 | 支持 |
累加聚合 | SELECT count(*) FROM t_order; SELECT sum(user_id) FROM t_order; | 支持 | 支持 |
比較聚合 |
SELECT max(user_id) FROM t_order; SELECT min(user_id) FROM t_order; |
支持 | 支持 |
平均聚合 | SELECT avg(order_id) FROM t_order; | 不支持 | 支持 |
分組 |
SELECT user_id, MAX(order_id) FROM t_order GROUP BY user_id; SELECT sum(user_id), order_id FROM t_order GROUP BY order_id; SELECT sum(user_id), test_int FROM t_order GROUP BY test_int; SELECT count(order_id), status FROM t_order GROUP BY status; (status 為 VARCHAR 類型) |
前 3 句支持 第 4 句不支持 | 支持 |
排序 / 分頁 |
SELECT FROM t_order ORDER BY user_id; SELECT FROM t_order ORDER BY user_id LIMIT 10, 10; |
不支持 | 支持 |
去重 | SELECT DISTINCT test_int FROM t_order; | 支持 | 不支持 |
算式 | SELECT * FROM t_order WHERE user_id=7+1; | 支持 | 支持 |
關(guān)聯(lián)查詢 |
SELECT a.user_id, a.order_id, a.status, b.item_id FROM t_order a JOIN t_order_item b ON a.order_id = b.order_id; SELECT a.user_id, a.test_int, a.status, b.item_id, b.user_id FROM t_order a JOIN t_order_item b ON a.test_int = b.user_id; |
支持 | 支持 |
子查詢 |
SELECT x.user_id,x.status,x.item_id FROM (SELECT a.user_id, a.order_id, a.status, b.item_id FROM t_order a JOIN t_order_item b ON a.order_id = b.order_id) x; SELECT count(x.item_id) FROM (SELECT a.user_id, a.order_id, a.status, b.item_id FROM t_order a JOIN t_order_item b ON a.order_id = b.order_id) x; SELECT * FROM t_order WHERE test_int in (SELECT test_int FROM t_order); |
第 1 句支持 后 2 句不支持 | 前 2 句支持 第 3 句不支持 |
UNION | SELECT user_id, order_id, status FROM t_order UNION ALL SELECT item_id, order_id, user_id FROM t_order_item | 不支持 | 不支持 |
INSERT |
INSERT INTO t_order (order_id, user_id, status, test_int) VALUES (1000, 1, “INIT”, 1); INSERT INTO t_order (order_id, user_id, status, test_int) VALUES (1001, 2, “INIT”, 2), (1002, 3, “INIT”, 3); |
支持 | 支持 |
無列名 INSERT | INSERT INTO t_order VALUES (1000, 1, “INIT”, 1); | 不支持 | 支持 |
DELETE | DELETE FROM t_order WHERE user_id=1; | ||
(條件有分片鍵) DELETE FROM t_order WHERE test_int=1;(條件無分片鍵) | 支持 | 支持 | |
UPDATE | UPDATE t_order SET test_int=1 WHERE user_id=0; | 支持 | 支持 |
分片鍵 UPDATE | UPDATE t_order SET user_id=1 WHERE user_id=0; | 不支持 | 不支持 |
CREATE | CREATE TABLE messages (page BIGINT(20) UNSIGNED,time_created_ns BIGINT(20) UNSIGNED,message VARCHAR(10000),PRIMARY KEY (page, time_created_ns)) ENGINE=InnoDB | 支持 | 支持 |
ALTER | ALTER TABLE messages ADD COLUMN status VARCHAR(50); | 支持 | 支持 |
DROP | DROP TABLE messages; | 支持 | 支持 |
TCL | BEGIN; COMMIT; ROLLBACK; | 支持 | 支持 |
DAL | USE test_keyspace; DESC t_order; | ||
SHOW CREATE TABLE t_order; | 支持 | 支持 | |
DCL |
CREATE USER ‘test_user’@’%’ IDENTIFIED BY ‘test’; GRANT SELECT, INSERT ON test_keyspace. TO ‘test_user’@’%’; REVOKE INSERT ON test_keyspace. FROM ‘test_user’@’%’; DROP USER ‘test_user’@’%’; |
不支持 | 支持 |
從測試結(jié)果看來,對于常用的 SQL 類型,無論是 Vitess 還是 ShardingSphere 都可以比較好的支持。但是 Vitess 無法支持排序,因此也無法支持分頁對于部分應(yīng)用來說可能是比較嚴(yán)重的問題。相比 Vitess,ShardingSphere 除 DISTINCT 關(guān)鍵字以外,其他類型的 SQL 支持程度均持平或略有優(yōu)勢。通過 SharingSphere 的官方 issue 列表中可知,DISTINCT 的支持目前正在進(jìn)行中,相信不久之后就會支持。
分片路由
分布式數(shù)據(jù)庫將數(shù)據(jù)進(jìn)行分片的主要目的之一就是希望執(zhí)行的操作能分散在一個或其中數(shù)個分片中,而不是在所有分片中,因此如何觸發(fā)分片路由,縮小分片范圍也是需要重點關(guān)注的功能。
Vitess 在 VSchema Guide 文檔說明 Select、Update、Delete 通過 Where 條件中的等值條件進(jìn)行路由,等值條件僅包括了 = 及 IN;Insert 則根據(jù)插入字段是否包含分片鍵來進(jìn)行分片路由。
ShardingSphere 除了支持 Where 條件中的 = 及 IN 進(jìn)行分片路由之外,還可以通過 BETWEEN 進(jìn)行分片路由 (需要使用 RangeShardingAlgorithm 或 ComplexShardingStrategy),Insert 時同樣根據(jù)插入字段來進(jìn)行分片路由。
為了驗證分片路由的執(zhí)行條件,首先要開啟 MySQL 數(shù)據(jù)庫的 GENERAL_LOG 參數(shù)。
SET GLOBAL GENERAL_LOG = 1;
SHOW VARIABLES LIKE '%general_log%';
開啟該參數(shù)之后,MySQL 數(shù)據(jù)庫將會記錄所有執(zhí)行過的 SQL,通過查看分片庫中實際執(zhí)行的 SQL,來判斷是分片路由還是廣播。
之后在 Vitess 中執(zhí)行數(shù)個測試 SQL:
SELECT * FROM t_order WHERE user_id = 7;
SELECT * FROM t_order WHERE user_id in (7, 9);
SELECT * FROM t_order WHERE user_id=7 or user_id=11;
SELECT * FROM t_order WHERE user_id BETWEEN 7 AND 11;
從 Vitess 分片 1 的 general_log,找到 Mysql 實際執(zhí)行了如下 SQL:
select * from t_order where user_id in (9)
select * from t_order where (user_id = 7 or user_id = 11)
select * from t_order where user_id between 7 and 11
從 Vitess 分片 2 的 general_log,找到 Mysql 實際執(zhí)行了如下 SQL:
select * from t_order where user_id = 7
select * from t_order where user_id in (7)
select * from t_order where (user_id = 7 or user_id = 11)
select * from t_order where user_id between 7 and 11
由于 user_id=7 屬于分片 2,所以 SQL1 不會分發(fā)到分片 1 中,而 SQL2 也被實際改寫,只將 user_id=9 分發(fā)到了分片 1,說明對于 = 以及 IN,Vitess 的確能夠正確進(jìn)行路由分片; 因為 user_id 7 和 11 均屬于分片 2,所以對于等值 OR 查詢 Vitess 并沒有解析到條件內(nèi)部,而是直接執(zhí)行了廣播。
然后在 ShardingSphere 中執(zhí)行測試 SQL:
SELECT * FROM t_order WHERE order_id = 1007 AND user_id=7;
SELECT * FROM t_order WHERE order_id = 1007;
SELECT * FROM t_order WHERE order_id in (1007, 1008);
SELECT * FROM t_order WHERE order_id in (1007, 1009);
SELECT * FROM t_order WHERE order_id=1007 or order_id=1011;
從 ShardingSphere 分片 1 的 general_log,發(fā)現(xiàn) Mysql 實際執(zhí)行了如下 SQL:
SELECT * FROM t_order_1 WHERE order_id = 1007
SELECT * FROM t_order_0 WHERE order_id in (1007, 1008)
SELECT * FROM t_order_1 WHERE order_id in (1007, 1008)
SELECT * FROM t_order_1 WHERE order_id in (1007, 1009)
SELECT * FROM t_order_1 WHERE order_id=1007 or order_id=1011
SELECT * FROM t_order_1 WHERE order_id=1007 or order_id=1010
SELECT * FROM t_order_0 WHERE order_id=1007 or order_id=1010
從 ShardingSphere 分片 2 的 general_log,發(fā)現(xiàn) Mysql 實際執(zhí)行了如下 SQL:
SELECT * FROM t_order_1 WHERE order_id = 1007 AND user_id=7
SELECT * FROM t_order_1 WHERE order_id = 1007
SELECT * FROM t_order_0 WHERE order_id in (1007, 1008)
SELECT * FROM t_order_1 WHERE order_id in (1007, 1008)
SELECT * FROM t_order_1 WHERE order_id in (1007, 1009)
SELECT * FROM t_order_1 WHERE order_id=1007 or order_id=1011
SELECT * FROM t_order_1 WHERE order_id=1007 or order_id=1010
SELECT * FROM t_order_0 WHERE order_id=1007 or order_id=1010
ShardingSphere 的等值查詢和 Vitess 一樣,能準(zhǔn)確的確定對應(yīng)分片表進(jìn)行查詢,當(dāng) SQL 中存在庫級分片鍵 user_id 時(SQL1),ShardingSphere 只將 SQL 定位在了分片 2 的 t_order_1 分表;而查詢不帶有庫級分片時(SQL2),ShardingSphere 進(jìn)行了庫級的廣播,但仍然能夠?qū)?SQL 定位在 t_order_1 表;而對于 IN 方式,雖然能夠準(zhǔn)確的定位到分片表,但是不會對 IN 的條件進(jìn)行重寫(分片 1 的 SQL2-4);對于 OR 的等值查詢,ShardingSphere 能夠定位到具體的分片,比 Vitess 優(yōu)秀;最后由于測試用例使用的是 InlineShardingStrategy,因此無法對 BETWEEN AND 的 SQL 進(jìn)行測試。
經(jīng)過測試,Vitess 和 ShardingSphere 都可以對等值條件進(jìn)行準(zhǔn)確的分片路由;ShardingSphere 相比于 Vitess 多支持了 OR 等值的分片路由,并且在實現(xiàn)了特定算法或特定策略時,還能夠支持 BETWEEN AND 的分片路由。
另外,對于強制分片路由,Vitess 在 FAQ 中回答需要用戶直接連接到對應(yīng)分片的 vttablet 進(jìn)行操作,而 ShardingSphere 支持 Hint 方式進(jìn)行強制分片路由,依舊使得分片對應(yīng)用透明。由此看來,ShardingSphere 在分片路由上的功能,也要略強于 Vitess。
路由條件 | Vitess | ShardingSphere |
---|---|---|
= 值 | 正確路由 | 正確路由 |
IN | 正確路由 | 正確路由 |
OR 等值 | 直接廣播 | 正確路由 |
BETWEEN AND | 直接廣播 | 正確路由需要用戶實現(xiàn)特定算法接口 |
結(jié)果歸并
當(dāng)分片路由將 SQL 路由到多個分片,或無法使用分片路由而進(jìn)行廣播時,如何將多個分片的結(jié)果合并為一個正確的結(jié)果,就涉及到結(jié)果歸并。
Vitess 在文檔中沒有對結(jié)果歸并詳細(xì)的說明,從在之前的 SQL 測試中能夠發(fā)現(xiàn),Vitess 對于一般的結(jié)果僅是簡單的將各個分片的結(jié)果集按照分片順序連接起來;對于部分聚合的結(jié)果歸并,如 count 和 sum,Vitess 能夠正確的進(jìn)行合并;但是對于一些復(fù)雜的歸并類型,比如 avg 或 order by 的結(jié)果歸并,就無法支持;在測試過程中,還發(fā)現(xiàn) Vitess 會對 Limit 的分頁 SQL 進(jìn)行改寫,比如分頁 SQL
SELECT * FROM t_order LIMIT 10,10;
就會改寫成
SELECT * FROM t_order LIMIT 20;
然后將 2 個分片的結(jié)果集合并之后再獲取 10~20 的結(jié)果。
ShardingSphere 在文檔 歸并引擎 一節(jié)中對結(jié)果歸并有非常詳細(xì)的描述,將歸并分類為遍歷、排序、分組、分頁和聚合 5 種類型。不僅和 Vitess 一樣能夠?qū)⒎制慕Y(jié)果集普通地連接起來,而且還支持了 avg 和 order by 的結(jié)果歸并。同時對于 Limit 分頁 SQL,也進(jìn)行了改寫。
正是由于 ShardingSphere 對結(jié)果歸并有著更好的支持,所以 ShardingSphere 在 SQL 支持上能夠比 Vitess 表現(xiàn)的更好。
分布式事務(wù)
事務(wù)是數(shù)據(jù)庫中一個重要且常用的功能,對于分布式數(shù)據(jù)庫而言同樣不可或缺。因此 Vitess 和 ShardingSphere 都提供了一些可選的分布式事務(wù)功能。
Vitess 提供了 3 個級別的分布式事務(wù),單庫事務(wù)、多庫事務(wù)、兩階段提交事務(wù),用戶可選擇其中一種作為 Vitess 的分布式事務(wù)實現(xiàn):
單庫事務(wù)指的是僅允許單個數(shù)據(jù)庫事務(wù)。嘗試超出單個數(shù)據(jù)庫的任何事務(wù)都將失敗。
多庫事務(wù)允許事務(wù)跨越多個數(shù)據(jù)庫,但每個數(shù)據(jù)庫均為單獨提交,即弱 XA,可能會出現(xiàn)部分提交導(dǎo)致數(shù)據(jù)不一致,且無法回滾。
兩階段提交類似于多庫事務(wù),但能保持多數(shù)據(jù)庫間的原子性,即其中一個數(shù)據(jù)庫提交失敗時,其他數(shù)據(jù)庫的提交將會回滾以保持?jǐn)?shù)據(jù)一致。
ShardingSphere 同樣提供了 3 種類型的分布式事務(wù),本地事務(wù)、XA 事務(wù)及柔性事務(wù)(開發(fā)中,預(yù)計 3.1.0 發(fā)布):
本地事務(wù)類似于 Vitess 的多庫事務(wù),各個數(shù)據(jù)庫獨立提交,即弱 XA。
XA 事務(wù)即兩階段提交事務(wù),默認(rèn)采用 Atomikos 事務(wù)管理器。
柔性事務(wù)采用 SAGA 模型進(jìn)行事務(wù)控制,以保證數(shù)據(jù)的最終一致性。其中 ShardingSphere 在 3.x 之前的版本也使用過最大努力送達(dá)型事務(wù),但由于無回滾能力,因此已經(jīng)廢棄,轉(zhuǎn)而使用能力更加強大的 SAGA。
Vitess 和 ShardingSphere 當(dāng)前版本的分布式事務(wù)功能相當(dāng),但是 Vitess 的官方文檔和 roadmap 計劃中,似乎沒有實現(xiàn)柔性事務(wù)的計劃,因此一旦 ShardingSphere 3.1.0 中支持柔性事務(wù),在分布式事務(wù)功能上將能支持更多的應(yīng)用場景。
讀寫分離
Vitess 的不提供默認(rèn)的讀寫分離功能,但是提供在 SQL 中通過 @指定的方式進(jìn)行從庫的查詢,例如在 SQL 中通過 ks@master 將查詢指向主庫,而使用 ks@replica 或 ks@rdonly 將查詢指向從庫或備庫。
ShardingSphere 的讀寫分離功能只需要在配置中指定主庫和從庫,ShardingSphere 能自動地將 DML 路由至主庫,DQL 路由至從庫;同時 ShardingSphere 允許多個從庫并配置負(fù)載均衡策略將請求疏導(dǎo)到不同的從庫;另外 ShardingSphere 還可以通過 Hint 進(jìn)行強制主庫路由。
ShardingSphere 的讀寫分離功能,無論從對 SQL 的入侵程度,還是從功能的實現(xiàn)程度,都略強于 Vitess 的讀寫分離。
分布式主鍵
Vitess 的分布式主鍵,用戶可通過設(shè)定全局非分片的外部查詢表來實現(xiàn)。如 Vitess 在官方文檔中的用例,將 user_id(主分片鍵)列配上全局序列表 user_seq,組成自增分布式主鍵;
ShardingSphere 提供靈活的配置分布式主鍵生成策略方式。 在分片規(guī)則配置中可配置每個表的主鍵生成策略,默認(rèn)使用雪花算法(snowflake)生成 64bit 的長整型數(shù)據(jù)。ShardingSphere 的雪花算法的時間紀(jì)元從 2016 年 11 月 1 日零點開始,可以使用到 2156 年,相信能滿足絕大部分系統(tǒng)的要求。
管理功能對比
配置管理
Vitess 將數(shù)據(jù)庫信息、分片信息等元數(shù)據(jù)信息,存儲在 zookeeper 或 Etcd 注冊中心中,并配以 GUI 系統(tǒng) vtctld 和命令行系統(tǒng) vtctl 對 Vitess 的功能進(jìn)行管理和控制。同時 Vitess 提供 workflows,將一些常用操作流程,變成可控制的工作流,使運維人員能夠自動快速地執(zhí)行諸如主從切換、數(shù)據(jù)遷移、平衡分片等操作。
ShradingSphere 同樣可以將分片信息,配置信息等元數(shù)據(jù),存儲在 zookeeper 或 Etcd 注冊中心中,但暫時沒有提供 GUI 或命令控制臺功能,對配置和 ShardingSphere 程序進(jìn)行控制和管理,用戶需要在 zookeeper 或 Etcd 的 API 或自帶的控制臺中,修改其中的信息。
監(jiān)控
Vitess 在 vtagate 和 vttablet 中提供了簡易的 GUI,用戶通過 GUI 頁面不僅能夠查看 Vitess 本身部分組件的健康狀況,QPS 等信息,還能獲取一部分底層數(shù)據(jù)庫的監(jiān)控信息。
ShardingSphere 自身并不提供監(jiān)控,但是可以通過一些 APM 系統(tǒng)進(jìn)行應(yīng)用監(jiān)控。目前 ShardingSphere 提供兩種方式對接應(yīng)用性能監(jiān)控系統(tǒng):
使用 OpenTracing API 發(fā)送性能追蹤數(shù)據(jù)。面向 OpenTracing 協(xié)議的 APM 產(chǎn)品都可以和 ShardingSphere 自動對接,比如 SkyWalking,Zipkin 和 Jaeger。
使用 SkyWalking 的自動探針。
數(shù)據(jù)庫管理
Vitess 提供了備份數(shù)據(jù)庫數(shù)據(jù)的功能,能將數(shù)據(jù)庫的數(shù)據(jù)、配置,連同 vttablet 一同備份到 NFS、云存儲或本地文件系統(tǒng)中,在備份的過程中,還能進(jìn)行自動壓縮以提高備份效率,并且 Vitess 可以從備份中快速創(chuàng)建出 vttable 并加入集群中。Vitess 還提供了主從切換和重設(shè)主從關(guān)系的功能,該功能不僅可以由 DBA 有計劃的使用 workflow 執(zhí)行,還可以在數(shù)據(jù)庫節(jié)點失效或有問題時自動執(zhí)行。Vitess 也提供了重分片 (Resharding) 的數(shù)據(jù)遷移方式,使得用戶能夠在修改分片規(guī)則后平滑地將舊分片的數(shù)據(jù)遷移到新分片上,Vitess 會在新分片上復(fù)制,驗證和保持?jǐn)?shù)據(jù)最新,而現(xiàn)有分片繼續(xù)提供實時讀寫流量。當(dāng) Vitess 準(zhǔn)備切換時,只需幾秒鐘的只讀停機時間即可進(jìn)行遷移。在切換執(zhí)行期間,可以讀取現(xiàn)有數(shù)據(jù),但無法寫入新數(shù)據(jù)。
ShardingSphere 目前僅提供了熔斷實例和禁用從庫的功能,在 roadmap 中還規(guī)劃實現(xiàn)多數(shù)據(jù)副本和彈性伸縮的功能。
總結(jié)
Vitess 和 ShardingSphere 作為當(dāng)下優(yōu)秀的數(shù)據(jù)庫中間件和分布式數(shù)據(jù)庫解決方案,在數(shù)據(jù)分片、分布式事務(wù)和數(shù)據(jù)庫治理等功能上均有所建樹,但是雙方在功能側(cè)重上有部分差異。
關(guān)于數(shù)據(jù)分片、分布式事務(wù)等 OTLP 應(yīng)用功能方面,ShardingSphere 比 Vitess 提供了更豐富和自由的分片方式、提供了更多的 SQL 支持和更容易觸發(fā)的分片路由、提供了侵入性更低的讀寫分離并即將提供更多種的分布式事務(wù)類型。因此 ShardingSphere 在應(yīng)用功能方面要強于 Vitess。
而關(guān)于管理方面的功能,Vitess 相比 ShardingSphere 增加了 GUI 的控制方式、提供了數(shù)據(jù)庫的備份和主從切換功能、并提供部分自身和數(shù)據(jù)庫的監(jiān)控。因此 Vitess 在管理方面的功能要優(yōu)于 ShardingSphere。
ShardingSphere 還在快速發(fā)展中,未來也會對數(shù)據(jù)庫治理及彈性數(shù)據(jù)遷移做大量工作。如果目前想找一個完美的在線功能 + 管理功能的解決方案,可以混合部署,在線查詢更新用 ShardingSphere,然后使用 Vitess 進(jìn)行數(shù)據(jù)的管理和監(jiān)控,并可以自行開發(fā)插件,同步 Vitess 和 ShardingSphere 的注冊中心配置,使其動態(tài)生效。
最后,通過一個簡單的表格,總結(jié)一下 Vitess 和 ShardingSphere 的對比結(jié)論:
Vitess | ShardingSphere | |
---|---|---|
分片模式 | 僅分庫 | 分庫 + 分表 + 分庫分表 |
SQL 支持 | 略少于 ShardingSphere | 略多于 Vitess |
分片路由 | 支持 = 和 IN | 支持 =、IN、OR、BETWEEN AND 允許用戶 Hint 強制路由 |
分布式事務(wù) | 1PC(弱 XA)和 2PC(強 XA) | 1PC(弱 XA)、2PC(強 XA) 將支持柔性事務(wù) SAGA |
讀寫分離 | 在 SQL 中指向主庫或從庫 | 配置之后由 ShardingSphere 自動路由 |
分布式主鍵 | 通過全局非分片序列表實現(xiàn) | 實現(xiàn)接口,默認(rèn)使用雪花算法 |
配置管理 | 支持 Zookeeper 和 Etcd 提供 2 類管理端 | 支持 Zookeeper 和 Etcd 暫無管理端 |
數(shù)據(jù)庫治理 | 提供簡單數(shù)據(jù)庫監(jiān)控 提供數(shù)據(jù)備份、主從切換、重分片數(shù)據(jù)遷移等 | 僅提供熔斷、禁用從庫功能 |
審核編輯 黃宇
-
數(shù)據(jù)庫
+關(guān)注
關(guān)注
7文章
3799瀏覽量
64396 -
開源
+關(guān)注
關(guān)注
3文章
3349瀏覽量
42501 -
分布式數(shù)據(jù)庫
+關(guān)注
關(guān)注
0文章
8瀏覽量
7610
發(fā)布評論請先 登錄
相關(guān)推薦
評論