sharding-jdbc初識,中小型項目分庫分表的福音

原創不易,請多多支持!對Java技術感興趣的童鞋請關注我,後面技術分享更精彩。 

介紹

mysql幾乎成為現在後臺項目開發的標配。雖然流行,但還是有弊端。單表超過5000w數據時,查詢性能將急劇下降。一般業務發展到這個時候,分庫分表將是繞不開的話題。但針對一些小的團隊,自己設計分庫分表邏輯,可能存在難度高、bug多的問題。使用mycat,又有些大材小用。文本將推薦一款小巧、便捷的分庫分表組件 --- sharding-jdbc。希望在項目開發中對廣大coder有所幫助。

sharding-jdbc最初是噹噹內部的一個架構組件,經過實際項目的身經百鍊,不斷抽象提取其通用性,開源出來的一套分庫分表框架實現。現已貢獻給Apache開源基金會,屬於ShardingSphere中的一部分。

sharding-jdbc以jar包依賴的方式集成到項目中,在jdbc層實現sql解析、路由和歸併等操作,對業務層透明。僅需簡單配置,原有業務代碼幾乎無需改動即可使用。

架構

由於本文著重推薦sharding-jdbc,對ShardingSphere將不做過多介紹,有興趣額的童鞋可以去以下官網瞭解。

https://shardingsphere.apache.org/document/current/cn/overview/

sharding-jdbc定位為輕量級Java框架,在Java的JDBC層提供的額外服務。 它使用客戶端直連數據庫,以jar包形式提供服務,無需額外部署和依賴,可理解為增強版的JDBC驅動,完全兼容JDBC和各種ORM框架。

  • 適用於任何基於Java的ORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC。
  • 基於任何第三方的數據庫連接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP等。
  • 支持任意實現JDBC規範的數據庫。目前支持MySQL,Oracle,SQLServer和PostgreSQL。
sharding-jdbc初識,中小型項目分庫分表的福音

上圖中sharding-jdbc應用於jdbc層,對業務層無感知,可以不影響原有邏輯的情況下平滑使用。當然,分佈式分庫、分表存在她的侷限性,分庫表最好是單表查詢,不建議摻雜多表的join、union等操作。

使用

為了便於演示,這裡只以訂單表的分表使用作為樣例。開始前,請先了解以下兩個概念。

邏輯表

水平拆分的數據表的相同邏輯和數據結構表的總稱。例:訂單數據根據主鍵尾數拆分為10張表,分別是order_0到order_9,他們的邏輯表名為order。

真實表

在分片的數據庫中真實存在的物理表。即上個示例中的order_0到order_9。

jar依賴

這裡以springboot項目為例。項目中新增以下starter依賴。

<dependency>
<groupid>org.apache.shardingsphere/<groupid>
<artifactid>sharding-jdbc-spring-boot-starter/<artifactid>
<version>4.0.0-RC1/<version>
/<dependency>

規則配置

在spring application.yml文件中添加以下配置

spring:
main:
# sharding-jdbc定義了重複的dataSource數據源bean,啟動時必須添加以下值
allow-bean-definition-overriding: true
# sharding-jdbc 分庫、分表配置
shardingsphere:
datasource:
names: ds0
ds0:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://localhost:3306/dctl_demo
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
sharding:
# default-database-strategy:
# inline:
# sharding-column: user_id
# algorithm-expression: ds$->{user_id % 2}
tables:
#分表的邏輯表表名
order:
#分表的物理表節點,數據源ds0下的order0...order9,共10張表
actual-data-nodes: ds0.order$->{0..9}
table-strategy:
inline:
#分片規則對應列,即以user_id值作為分片規則的列
sharding-column: user_id
#分片按user_id列和10取模運算,路由到對應的order0...9的表
algorithm-expression: order$->{user_id % 10}

由於本文僅涉及分表,不涉及分庫。所以分庫配置default-database-strategy被屏蔽。

有分庫需求的對應著規則修改即可。

表結構

新建邏輯表,表結構如下

CREATE TABLE `order` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '訂單id',
`user_id` bigint(20) unsigned NOT NULL COMMENT '用戶id',
`product_id` bigint(20) unsigned NOT NULL COMMENT '產品id',
`price` decimal(8,2) DEFAULT '0.00' COMMENT '商品價格',
`create_time` datetime DEFAULT NULL COMMENT '創建時間',
`create_by` varchar(255) DEFAULT NULL COMMENT '創建人',
`update_time` datetime DEFAULT NULL COMMENT '更新時間',
`update_by` varchar(255) DEFAULT NULL COMMENT '更新人',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

按上面邏輯表,新建訂單對應的10張物理表。

sharding-jdbc初識,中小型項目分庫分表的福音

測試服務

新增訂單controller。

sharding-jdbc初識,中小型項目分庫分表的福音

啟動工程,模擬post請求,構建訂單。

sharding-jdbc初識,中小型項目分庫分表的福音

響應結果

sharding-jdbc初識,中小型項目分庫分表的福音

數據庫記錄查看

由於分表規則以user_id來分片,並按10取模路由實際表。測試數據是user_id=9,取模後定位到order9這張表中。查看相應表,下圖可見數據已經成功寫入到相應表中。

sharding-jdbc初識,中小型項目分庫分表的福音

總結

到此,整個集成已全部完成,是否感覺對項目業務的侵入性很小?簡單、快捷,分庫分表so easy!

再來回顧下整個集成過程

  1. 首先依賴引入。
  2. 定義分庫分表的分片規則,配置文件表、分片列、分片表達式等修改。
  3. 數據庫創建邏輯表和真實表。
  4. 按原有方式編寫sql代碼邏輯。

看上去很簡單,但使用時一定要清楚sharding-jdbc的使用場景,過多的sql join切記不要使用,否則多庫多表查詢時,可能造成框架的笛卡爾集掃描,導致每個庫、每張表都被查詢,最終嚴重影響系統性能。

若業務需求避免不了多表查詢,請把join的sql拆成多個,先查分表的值。用查到的值作為條件,再到另一個sql中查詢。

最後,希望本文對有耐心看到最後的童鞋有所幫助。有相應問題和意見,歡迎指正。


分享到:


相關文章: