Amazon Aurora 讀寫能力擴充套件之 ShardingSphere-JDBC 篇

SphereEx發表於2022-04-27

文章來源亞馬遜 AWS 官方部落格


孫進華,亞馬遜雲科技資深解決方案架構師,負責幫助客戶進行上雲架構的設計和諮詢。加入 AWS 前自主創業負責電商平臺搭建和車企電商平臺整體架構設計。曾就職於全球領先的通訊裝置公司,擔任高階工程師,負責 LTE 裝置系統的多個子系統的開發與架構設計。在高併發、高可用系統架構設計、微服務架構設計、資料庫、中介軟體、IOT 等方面有著豐富的經驗。

1. 前言

Amazon Aurora 是亞馬遜雲科技自研的一項關聯式資料庫服務,它在提供和開源資料庫 MySQL、PostgreSQL 的完好相容性同時,也能夠提供和商業資料庫媲美的效能和可用性。效能方面,Aurora MySQL 能夠支援到與開源標準 MySQL 同等配置下五倍的吞吐量,Aurora PostgreSQL 能夠支援與開源標準 PostgreSQL 同等配置下三倍的吞吐量的提升。在擴充套件性的角度,Aurora 在儲存與計算、橫向與縱向方面都進行了功能的增強和創新。

Aurora 的最大資料儲存量現在支援多達 128TB,而且可以支援儲存的動態收縮。計算方面,Aurora 提供多個讀副本的可擴充套件性配置支援一個區域內多達 15 個讀副本的擴充套件,提供多主的架構來支援同一個區域內 4 個寫節點的擴充套件,提供 Serverless 無伺服器化的架構例項級別的秒級縱向擴充套件,提供全球資料庫來實現資料庫的低延遲跨區域擴充套件。

隨著使用者資料量的增長,Aurora 已經提供了很好的擴充套件性,那是否可以進一步增強更多的資料量、更多的併發訪問能力呢?您可以考慮利用分庫分表的方式,來支援底層多個 Aurora 叢集的配置。基於此,包含這篇部落格在內的系列部落格會進行相應的介紹,旨在為您進行分庫分表時代理或者 JDBC 的選擇提供參考。

1.1 為什麼要分庫分表


AWS Aurora 提供了關係型資料庫單機,主從,多主,全球資料庫等託管架構形式可以滿足以上各種架構場景,但分庫分表的場景下 Aurora 沒有提供直接的支援,並且分庫分表還衍生出來如垂直與水平多種形態,再進一步提升資料容量的情況下,也帶來一些需要解決的問題,如跨節點資料庫 Join 關聯查詢、分散式事務、執行的 SQL 排序、翻頁、函式計算、資料庫全域性主鍵、容量規劃、分庫分表後二次擴容等問題。

1.2 分庫分表的方式

查詢一次所花的時間業界公認 MySQL 單表容量在 1 千萬以下是最佳狀態,因為這時它的BTREE索引樹高在 3~5 之間。透過對資料的切分可以在降低單表的資料量的同時,將讀寫的壓力分攤到不同的資料節點上,資料切分可以分為:垂直切分和水平切分。


垂直切分的優點

  • 解決業務系統層面的耦合,業務清晰;

  • 與微服務的治理類似,也能對不同業務的資料進行分級管理、維護、監控、擴充套件等;

  • 高併發場景下,垂直切分一定程度的提升 IO、資料庫連線數、單機硬體資源的瓶頸。

垂直切分的缺點

  • 分庫後無法 Join,只能透過介面聚合方式解決,提升了開發的複雜度;

  • 分庫後分布式事務處理複雜;

  • 依然存在單表資料量過大的問題(需要水平切分)。

水平切分的優點

  • 不存在單庫資料量過大、高併發的效能瓶頸,提升系統穩定性和負載能力;

  • 應用端改造較小,不需要拆分業務模組。

水平切分的缺點

  • 跨分片的事務一致性難以保證;

  • 跨庫的 Join 關聯查詢效能較差;

  • 資料多次擴充套件難度和維護量極大。

結合以上分析,在調研了常見的分庫分表的中介軟體基礎上,我們選取 ShardingSphere 開源產品結合 Amazon Aurora,介紹這兩種產品的結合是如何滿足各種形式的分庫分表方式和如何解決由分庫分錶帶來的一些問題。

2. Sharding-JDBC 功能測試

2.1 樣例工程說明

下載樣例工程程式碼到本地,為保證測試程式碼的穩定性我們這裡選擇使 shardingsphere-example-4.0.0 這個 tag 版本。

git clone 

工程專案說明:

shardingsphere-example
  ├── example-core
  │   ├── config-utility
  │   ├── example-api
  │   ├── example-raw-jdbc
  │   ├── example-spring-jpa #spring+jpa整合基礎的entity,repository  │   └── example-spring-mybatis
  ├── sharding-jdbc-example
  │   ├── sharding-example
  │   │   ├── sharding-raw-jdbc-example
  │   │   ├── sharding-spring-boot-jpa-example #整合基礎的sharding-jdbc的功能  │   │   ├── sharding-spring-boot-mybatis-example
  │   │   ├── sharding-spring-namespace-jpa-example
  │   │   └── sharding-spring-namespace-mybatis-example
  │   ├── orchestration-example
  │   │   ├── orchestration-raw-jdbc-example
  │   │   ├── orchestration-spring-boot-example #整合基礎的sharding-jdbc的治理的功能  │   │   └── orchestration-spring-namespace-example
  │   ├── transaction-example
  │   │   ├── transaction-2pc-xa-example #sharding-jdbc分散式事務兩階段提交的樣例  │   │   └──transaction-base-seata-example #sharding-jdbc分散式事務seata的樣例  │   ├── other-feature-example
  │   │   ├── hint-example
  │   │   └── encrypt-example
  ├── sharding-proxy-example
  │   └── sharding-proxy-boot-mybatis-example
  └── src/resources
        └── manual_schema.sql

配置檔案說明: 

application-master-slave.properties #讀寫分離配置檔案application-sharding-databases-tables.properties #分庫分表配置檔案application-sharding-databases.properties       #僅分庫配置檔案application-sharding-master-slave.properties    #分庫分表加讀寫分離的配置檔案application-sharding-tables.properties          #分表配置檔案application.properties                         #spring boot 配置檔案

程式碼邏輯說明:

Spring Boot 應用的入口類,執行該類就可以執行工程


其中 demo 的執行邏輯如下:


2.2讀寫分離驗證

隨著業務增長,寫和讀請求分離到不同的資料庫節點上能夠有效提高整個資料庫叢集的處理能力。Aurora 透過讀/寫的 endpoint 可以滿足使用者寫和強一致性讀的需求,單獨只讀的 endpoint 可以滿足使用者非強一致性讀的需求。Aurora 的讀寫延遲通常在毫秒級別,比 MySQL 基於 binlog 的邏輯複製要低得多,所以有很多負載是直接打到只讀 endpoint。

透過一主多從的配置方式,可以將查詢請求均勻的分散到多個資料副本,能夠進一步的提升系統的處理能力。讀寫分離雖然可以提升系統的吞吐量和可用性,但同時也帶來了資料不一致的問題。Aurora 以完全託管的形式提供了主從架構,但上層應用在與 Aurora 互動時,仍然需要管理多個資料來源,根據 SQL 語句的讀寫型別和一定的路由策略將 SQL 請求路由到不同的節點上。

Sharding-JDBC 提供的讀寫分離的特性,應用程式與 Sharding-JDBC 整合,將應用程式與資料庫叢集之間複雜配置關係從應用程式中剝離出來,開發者透過配置檔案管理 Shard,再結合一些 ORM 框架如 Spring JPA、Mybatis 就可以完全將這些複製的邏輯從程式碼中分離。極大的提高程式碼的可維護性,降低程式碼與資料庫的耦合。

2.2.1 資料庫環境準備

首先建立一套 Aurora MySQL 讀寫分離叢集,機型為 db.r5.2xlarge,每套叢集有一個寫節點 2 個讀節點。如下圖所示



2.2.2 Sharding-JDBC 配置

application.properties spring boot 主配置檔案說明

如下圖所屬:綠色標註的部分你需要替換成自己環境上的配置

# jpa自動根據實體建立和drop資料表spring.jpa.properties.hibernate.hbm2ddl.auto=create-dropspring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jpa.properties.hibernate.show_sql=true#spring.profiles.active=sharding-databases#spring.profiles.active=sharding-tables#spring.profiles.active=sharding-databases-tables#啟用master-slave 配置項,這樣sharding-jdbc將使用master-slave配置檔案spring.profiles.active=master-slave#spring.profiles.active=sharding-master-slave

application-master-slave.properties sharding-jdbc 配置檔案說明

spring.shardingsphere.datasource.names=ds_master,ds_slave_0,ds_slave_1
# 資料來源 主庫-master
spring.shardingsphere.datasource.ds_master.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds_master.password= 您自己的主db密碼
spring.shardingsphere.datasource.ds_master.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds_master.jdbc-url=您自己的主db資料來源url spring.shardingsphere.datasource.ds_master.username=您自己的主db使用者名稱 
# 資料來源 從庫
spring.shardingsphere.datasource.ds_slave_0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds_slave_0.password= 您自己的從db密碼
spring.shardingsphere.datasource.ds_slave_0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds_slave_0.jdbc-url=您自己的從db資料來源url
spring.shardingsphere.datasource.ds_slave_0.username= 您自己的從db使用者名稱
# 資料來源 從庫
spring.shardingsphere.datasource.ds_slave_1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds_slave_1.password=您自己的從db密碼
spring.shardingsphere.datasource.ds_slave_1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds_slave_1.jdbc-url= 您自己的從db資料來源url
spring.shardingsphere.datasource.ds_slave_1.username= 您自己的從db使用者名稱
# 路由策略配置
spring.shardingsphere.masterslave.load-balance-algorithm-type=round_robin
spring.shardingsphere.masterslave.name=ds_ms
spring.shardingsphere.masterslave.master-data-source-name=ds_master
spring.shardingsphere.masterslave.slave-data-source-names=ds_slave_0,ds_slave_1
# sharding-jdbc 配置資訊儲存方式
spring.shardingsphere.mode.type=Memory
# 開啟shardingsphere 日誌,開啟的情況下從列印中可以看到邏輯SQL到實際SQL的轉換
spring.shardingsphere.props.sql.show=true

2.2.3 測試驗證過程說明

  • 測試環境資料初始化:Spring JPA 初始化自動建立用於測試的表


  • 在主例項上寫入資料

如下圖 ShardingSphere-SQL log 所示,寫 SQL 在 ds_master 資料來源上執行。


  • 資料查詢操作在從庫上執行

如下圖 ShardingSphere-SQL log 所示,讀 SQL 按照輪詢的方式在 ds_slave 資料來源上執行。

[INFO ] 2022-04-02 19:43:39,376 --main-- [ShardingSphere-SQL] Rule Type: master-slave 
[INFO ] 2022-04-02 19:43:39,376 --main-- [ShardingSphere-SQL] SQL: select orderentit0_.order_id as order_id1_1_, orderentit0_.address_id as address_2_1_, 
orderentit0_.status as status3_1_, orderentit0_.user_id as user_id4_1_ from t_order orderentit0_ ::: DataSources: ds_slave_0 
---------------------------- Print OrderItem Data -------------------
Hibernate: select orderiteme1_.order_item_id as order_it1_2_, orderiteme1_.order_id as order_id2_2_, orderiteme1_.status as status3_2_, orderiteme1_.user_id as user_id4_2_ from t_order orderentit0_ cross join t_order_item orderiteme1_ where orderentit0_.order_id=orderiteme1_.order_id
[INFO ] 2022-04-02 19:43:40,898 --main-- [ShardingSphere-SQL] Rule Type: master-slave 
[INFO ] 2022-04-02 19:43:40,898 --main-- [ShardingSphere-SQL] SQL: select orderiteme1_.order_item_id as order_it1_2_, orderiteme1_.order_id as order_id2_2_, orderiteme1_.status as status3_2_, 
orderiteme1_.user_id as user_id4_2_ from t_order orderentit0_ cross join t_order_item orderiteme1_ where orderentit0_.order_id=orderiteme1_.order_id ::: DataSources: ds_slave_1

注意:如下圖所示,如果在一個事務中既有讀也有寫,Sharding-JDBC 將讀寫操作都路由到主庫;如果讀寫請求不在一個事務中,那麼對應讀請求將按照路由策略分發到不同的讀節點上。

@Override@Transactional // 開啟事務時在該事務中讀寫都走主庫;關閉事務時,讀走從庫,寫走主庫public void processSuccess() throws SQLException {
    System.out.println("-------------- Process Success Begin ---------------");
    List<Long> orderIds = insertData();
    printData();
    deleteData(orderIds);
    printData();
    System.out.println("-------------- Process Success Finish --------------");
}

2.2.4 Aurora failover 場景驗證

Aurora 資料庫環境採用 2.2.1 中的配置。

2.2.4.1 驗證過程中說明

  • 啟動 Spring-Boot 工程
  • 在 Aurora 的 console 上執行故障轉移操作


  • 執行 Rest API 請求
  • 多次執行 POST () 直到該 API 的呼叫寫入 Aurora 失敗到最終恢復成功。

  • 觀測執行程式碼 failover 過程如下圖所示,從 log 可以分析最近一次 SQL 執行寫入操作成功到下次執行再次寫入成功大概需要 37s,也就是應用從 Aurora failover 中可以自動恢復,恢復的時長大概是 37s。


2.3僅分表功能驗證

2.3.1 Sharding-JDBC 配置

application.properties spring boot 主配置檔案說明

# jpa 自動根據實體建立和drop資料表spring.jpa.properties.hibernate.hbm2ddl.auto=create-dropspring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jpa.properties.hibernate.show_sql=true#spring.profiles.active=sharding-databases#啟用sharding-tables配置項#spring.profiles.active=sharding-tables#spring.profiles.active=sharding-databases-tables# spring.profiles.active=master-slave#spring.profiles.active=sharding-master-slave

application-sharding-tables.properties sharding-jdbc 配置檔案說明

## 主鍵策略配置spring.shardingsphere.sharding.tables.t_order.key-generator.column=order_id
spring.shardingsphere.sharding.tables.t_order.key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.tables.t_order.key-generator.props.worker.id=123spring.shardingsphere.sharding.tables.t_order_item.actual-data-nodes=ds.t_order_item_$->{0..1}
spring.shardingsphere.sharding.tables.t_order_item.table-strategy.inline.sharding-column=order_id
spring.shardingsphere.sharding.tables.t_order_item.table-strategy.inline.algorithm-expression=t_order_item_$->{order_id % 2}
spring.shardingsphere.sharding.tables.t_order_item.key-generator.column=order_item_id
spring.shardingsphere.sharding.tables.t_order_item.key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.tables.t_order_item.key-generator.props.worker.id=123# 配置t_order與 t_order_item的繫結關係spring.shardingsphere.sharding.binding-tables[0]=t_order,t_order_item# 配置廣播表spring.shardingsphere.sharding.broadcast-tables=t_address# sharding-jdbc的模式spring.shardingsphere.mode.type=Memory# 開啟shardingsphere日誌spring.shardingsphere.props.sql.show=true

2.3.2 測試驗證過程說明

  • DDL 操作

如下圖所屬,JPA 自動建立用於測試的表,在配置了 Sharding-JDBC 的路由規則的情況下,client 端執行 DDL,Sharding-JDBC 會自動根據分表規則建立對應的表;如 t address 是廣播表,由於只有一個主例項,所以建立一個 taddress;t order 按照取模分表,建立 torder 時會建立 t order0, t order1 兩張表物理表。


  • 寫操作

如下圖所示 Logic SQL 向 t order 插入一條記錄,Sharding-JDBC 執行的時候會根據分表規則將資料分佈放到 torder 0, torder_1 中。

當 t_order 和 t_order_item 配置了繫結關係時,order_item 與 order 有關聯關係的記錄會放到同一個物理分表中。


  • 讀操作

繫結表下的 join 查詢操作 order 和 order_item,如下圖所示,會根據繫結關係精確定位對應的物理 shard 上。


非繫結表下的 join 查詢操作 order 和 order_item,如下圖所屬,會遍歷所有的 shard。


2.4 僅分庫功能驗證

2.4.1 資料庫環境準備

如下圖所屬,在 Aurora 上建立兩個例項:ds_ 0 ds_1


啟動 Sharding-spring-boot-jpa-example 工程時會在兩個 Aurora 例項上建立表 t_order, t_order_item,t_address

2.4.2 Sharding-JDBC 配置

application.properties springboot 主配置檔案說明

# jpa 自動根據實體建立和drop資料表spring.jpa.properties.hibernate.hbm2ddl.auto=createspring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jpa.properties.hibernate.show_sql=true# 啟用sharding-databases配置項spring.profiles.active=sharding-databases#spring.profiles.active=sharding-tables#spring.profiles.active=sharding-databases-tables#spring.profiles.active=master-slave#spring.profiles.active=sharding-master-slave

application-sharding-databases.properties sharding-jdbc 配置檔案說明

spring.shardingsphere.datasource.names=ds_0,ds_1
# ds_0
spring.shardingsphere.datasource.ds_0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds_0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds_0.jdbc-url= spring.shardingsphere.datasource.ds_0.username= 
spring.shardingsphere.datasource.ds_0.password=
# ds_1
spring.shardingsphere.datasource.ds_1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds_1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds_1.jdbc-url= 
spring.shardingsphere.datasource.ds_1.username= 
spring.shardingsphere.datasource.ds_1.password=
spring.shardingsphere.sharding.default-database-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.default-database-strategy.inline.algorithm-expression=ds_$->{user_id % 2}spring.shardingsphere.sharding.binding-tables=t_order,t_order_item
spring.shardingsphere.sharding.broadcast-tables=t_address
spring.shardingsphere.sharding.default-data-source-name=ds_0
spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=ds_$->{0..1}.t_order
spring.shardingsphere.sharding.tables.t_order.key-generator.column=order_id
spring.shardingsphere.sharding.tables.t_order.key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.tables.t_order.key-generator.props.worker.id=123spring.shardingsphere.sharding.tables.t_order_item.actual-data-nodes=ds_$->{0..1}.t_order_item
spring.shardingsphere.sharding.tables.t_order_item.key-generator.column=order_item_id
spring.shardingsphere.sharding.tables.t_order_item.key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.tables.t_order_item.key-generator.props.worker.id=123# sharding-jdbc的模式
spring.shardingsphere.mode.type=Memory
# 開啟shardingsphere日誌
spring.shardingsphere.props.sql.show=true

2.4.3 測試驗證過程說明

  • DDL 操作

JPA 自動建立用於測試的表,如下圖所屬,在配置了 Sharding-JDBC 的分庫路由規則的情況下,client 端執行 DDL,Sharding-JDBC 會自動根據分表規則建立對應的表;如 t address 是廣播表在 ds0 和 ds 1 上都會建立物理表 taddress,t order,torder item 按照取模分庫,這三個表會分別在 ds0 和 ds_1 上建立。


  • 寫操作

對於廣播表 t address,每寫入一條記錄會在 ds0 和 ds 1 的 taddress 表上都寫入


對於分庫的表 t order,torder_item,會按照分庫欄位和路由策略寫入到對應例項上的表中。


  • 讀操作

如下圖所示,查詢 order,根據分庫路由規則路由到對應的 Aurora 例項上。


如下圖所示,查詢 Address,由於 address 是廣播表,會在所用的節點中隨機選擇一個 address 所在的例項查詢。


如下圖所示,繫結表下的 join 查詢操作 order 和 order_item 時,會根據繫結關係精確定位對應的物理 shard 上。 


2.5 分庫分表功能驗證

2.5.1 資料庫環境準備

如下圖所示,在 Aurora 上建立兩個例項:ds 0和ds1

啟動 sharding-spring-boot-jpa-example 工程時會在兩個 Aurora 例項上建立物理表 t_order_01, t_order_02, t_order_item_01,t_order_item_02 和 t_address 全域性表。


2.5.2 Sharding-JDBC 配置

application.properties springboot 主配置檔案說明

# jpa 自動根據實體建立和drop資料表spring.jpa.properties.hibernate.hbm2ddl.auto=createspring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jpa.properties.hibernate.show_sql=true# 啟用sharding-databases-tables配置項#spring.profiles.active=sharding-databases#spring.profiles.active=sharding-tablesspring.profiles.active=sharding-databases-tables#spring.profiles.active=master-slave#spring.profiles.active=sharding-master-slave

application-sharding-databases.properties sharding-jdbc 配置檔案說明

spring.shardingsphere.datasource.names=ds_0,ds_1
# ds_0
spring.shardingsphere.datasource.ds_0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds_0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds_0.jdbc-url= 306/dev?useSSL=false&characterEncoding=utf-8spring.shardingsphere.datasource.ds_0.username= 
spring.shardingsphere.datasource.ds_0.password=
spring.shardingsphere.datasource.ds_0.max-active=16# ds_1
spring.shardingsphere.datasource.ds_1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds_1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds_1.jdbc-url= 
spring.shardingsphere.datasource.ds_1.username= 
spring.shardingsphere.datasource.ds_1.password=
spring.shardingsphere.datasource.ds_1.max-active=16# 預設的分庫策略
spring.shardingsphere.sharding.default-database-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.default-database-strategy.inline.algorithm-expression=ds_$->{user_id % 2}spring.shardingsphere.sharding.binding-tables=t_order,t_order_item
spring.shardingsphere.sharding.broadcast-tables=t_address
# 不滿足分庫策略的表放在ds_0上
spring.shardingsphere.sharding.default-data-source-name=ds_0
# t_order分表策略
spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=ds_$->{0..1}.t_order_$->{0..1}spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.sharding-column=order_id
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.algorithm-expression=t_order_$->{order_id % 2}spring.shardingsphere.sharding.tables.t_order.key-generator.column=order_id
spring.shardingsphere.sharding.tables.t_order.key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.tables.t_order.key-generator.props.worker.id=123# t_order_item分表策略
spring.shardingsphere.sharding.tables.t_order_item.actual-data-nodes=ds_$->{0..1}.t_order_item_$->{0..1}spring.shardingsphere.sharding.tables.t_order_item.table-strategy.inline.sharding-column=order_id
spring.shardingsphere.sharding.tables.t_order_item.table-strategy.inline.algorithm-expression=t_order_item_$->{order_id % 2}spring.shardingsphere.sharding.tables.t_order_item.key-generator.column=order_item_id
spring.shardingsphere.sharding.tables.t_order_item.key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.tables.t_order_item.key-generator.props.worker.id=123# sharding-jdbc的模式
spring.shardingsphere.mode.type=Memory
# 開啟shardingsphere日誌
spring.shardingsphere.props.sql.show=true

2.5.3 測試驗證過程說明

  • DDL 操作

JPA 自動建立用於測試的表,如下圖所示,在配置了 Sharding-JDBC 的分庫分表路由規則的情況下,client 端執行 DDL,Sharding-JDBC 會自動根據分表規則建立對應的表;如 t address 是廣播表在 ds_0 和 ds_ 1 上都會建立 t_address。t_order,t_order_item 按照取模分庫分表,這三個表會分別在 ds0 和 ds_1 上建立。


  • 寫操作

對於廣播表 t address,每寫入一條記錄會在 ds0 和 ds 1 的 taddress 表上都寫入。


對於分庫的表 t order,torder_item,會按照分庫欄位和路由策略寫入到對應例項上的表中。


  • 讀操作

讀操作與僅分庫功能驗證類似,這裡不再贅述

2.6 分庫分表加讀寫分離功能驗證

2.6.1 資料庫環境準備

建立的資料庫例項於對應的物理表如下圖所示。



2.6.2 Sharding-JDBC 配置

application.properties spring boot 主配置檔案說明

# jpa 自動根據實體建立和drop資料表spring.jpa.properties.hibernate.hbm2ddl.auto=createspring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jpa.properties.hibernate.show_sql=true# 啟用sharding-databases-tables配置項#spring.profiles.active=sharding-databases#spring.profiles.active=sharding-tables#spring.profiles.active=sharding-databases-tables#spring.profiles.active=master-slavespring.profiles.active=sharding-master-slave

application-sharding-master-slave.properties sharding-jdbc 配置檔案說明

其中資料庫的 url、name、password 需要修改成你自己的資料庫的引數。

spring.shardingsphere.datasource.names=ds_master_0,ds_master_1,ds_master_0_slave_0,ds_master_0_slave_1,ds_master_1_slave_0,ds_master_1_slave_1
spring.shardingsphere.datasource.ds_master_0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds_master_0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds_master_0.jdbc-url= spring.shardingsphere.datasource.ds_master_0.username= 
spring.shardingsphere.datasource.ds_master_0.password=
spring.shardingsphere.datasource.ds_master_0.max-active=16spring.shardingsphere.datasource.ds_master_0_slave_0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds_master_0_slave_0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds_master_0_slave_0.jdbc-url= spring.shardingsphere.datasource.ds_master_0_slave_0.username= 
spring.shardingsphere.datasource.ds_master_0_slave_0.password=
spring.shardingsphere.datasource.ds_master_0_slave_0.max-active=16spring.shardingsphere.datasource.ds_master_0_slave_1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds_master_0_slave_1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds_master_0_slave_1.jdbc-url= spring.shardingsphere.datasource.ds_master_0_slave_1.username= 
spring.shardingsphere.datasource.ds_master_0_slave_1.password=
spring.shardingsphere.datasource.ds_master_0_slave_1.max-active=16spring.shardingsphere.datasource.ds_master_1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds_master_1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds_master_1.jdbc-url= 
spring.shardingsphere.datasource.ds_master_1.username= 
spring.shardingsphere.datasource.ds_master_1.password=
spring.shardingsphere.datasource.ds_master_1.max-active=16spring.shardingsphere.datasource.ds_master_1_slave_0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds_master_1_slave_0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds_master_1_slave_0.jdbc-url=
spring.shardingsphere.datasource.ds_master_1_slave_0.username=
spring.shardingsphere.datasource.ds_master_1_slave_0.password=
spring.shardingsphere.datasource.ds_master_1_slave_0.max-active=16spring.shardingsphere.datasource.ds_master_1_slave_1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds_master_1_slave_1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds_master_1_slave_1.jdbc-url= spring.shardingsphere.datasource.ds_master_1_slave_1.username=admin
spring.shardingsphere.datasource.ds_master_1_slave_1.password=
spring.shardingsphere.datasource.ds_master_1_slave_1.max-active=16spring.shardingsphere.sharding.default-database-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.default-database-strategy.inline.algorithm-expression=ds_$->{user_id % 2}spring.shardingsphere.sharding.binding-tables=t_order,t_order_item
spring.shardingsphere.sharding.broadcast-tables=t_address
spring.shardingsphere.sharding.default-data-source-name=ds_master_0
spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=ds_$->{0..1}.t_order_$->{0..1}spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.sharding-column=order_id
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.algorithm-expression=t_order_$->{order_id % 2}spring.shardingsphere.sharding.tables.t_order.key-generator.column=order_id
spring.shardingsphere.sharding.tables.t_order.key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.tables.t_order.key-generator.props.worker.id=123spring.shardingsphere.sharding.tables.t_order_item.actual-data-nodes=ds_$->{0..1}.t_order_item_$->{0..1}spring.shardingsphere.sharding.tables.t_order_item.table-strategy.inline.sharding-column=order_id
spring.shardingsphere.sharding.tables.t_order_item.table-strategy.inline.algorithm-expression=t_order_item_$->{order_id % 2}spring.shardingsphere.sharding.tables.t_order_item.key-generator.column=order_item_id
spring.shardingsphere.sharding.tables.t_order_item.key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.tables.t_order_item.key-generator.props.worker.id=123# 主從資料來源,分庫資料來源配置
spring.shardingsphere.sharding.master-slave-rules.ds_0.master-data-source-name=ds_master_0
spring.shardingsphere.sharding.master-slave-rules.ds_0.slave-data-source-names=ds_master_0_slave_0, ds_master_0_slave_1
spring.shardingsphere.sharding.master-slave-rules.ds_1.master-data-source-name=ds_master_1
spring.shardingsphere.sharding.master-slave-rules.ds_1.slave-data-source-names=ds_master_1_slave_0, ds_master_1_slave_1
# sharding-jdbc的模式
spring.shardingsphere.mode.type=Memory
# 開啟shardingsphere日誌
spring.shardingsphere.props.sql.show=true

2.6.3 測試驗證過程說明

  • DDL 操作所屬

JPA 自動建立用於測試的表,如下圖,在配置了 Sharding-JDBC 的分庫路由規則的情況下,client 端執行 DDL,Sharding-JDBC 會自動根據分表規則建立對應的表;如 taddress 是廣播表在 ds0 和 ds1 上都會建立, t_address,t_order,t_order_item 按照取模分庫,這三個表會分別在 ds0 和 ds_1 上建立。


  • 寫操作

對於廣播表 t address,每寫入一條記錄會在 ds0 和 ds 1 的 taddress 表上都寫入


對於分庫的表 t order,torder_item,會按照分庫欄位和路由策略寫入到對應例項上的表中。


  • 讀操作

繫結表下的 join 查詢操作 order 和 order_item,如下圖所示。


3. 結語

ShardingSphere 作為一款專注於資料庫增強的開源產品,從社群活躍度、產品成熟度、文件豐富程度上來看都是比較好的。其中的 Sharding-JDBC 是基於客戶端的分庫分表方案,它支援了所有的分庫分表的場景,並且無需引入 Proxy 這樣的中間層,所以降低了運維的複雜性,相比 Proxy 這種方式由於少了中間層所以時延理論上會比 Proxy 低,其次 Sharding-JDBC 可以支援各種基於 SQL 標準的關係型資料庫如 MySQL/PostgreSQL/Oracle/SQL Server 等。但由於 Sharding-JDBC 與應用程式整合,目前支援的語言僅限於 Java,對應用程式有一定的耦合性,但 Sharding-JDBC 將所以分庫分表的配置從應用程式中分離,這樣面臨切換其他的中介軟體時由此帶來的變更相對較小。綜上所述如果您不希望引入中間層,且使用基於 Java 語言開發的系統,且需要對接不同的關係型資料庫,Sharding-JDBC 將會是一個不錯的選擇。

歡迎點選連結,瞭解更多內容:

Apache ShardingSphere 官網:

Apache ShardingSphere GitHub 地址:

SphereEx 官網:

歡迎新增社群經理微信(ss_assistant_1)加入交流群,與眾多 ShardingSphere 愛好者一同交流。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70001955/viewspace-2889112/,如需轉載,請註明出處,否則將追究法律責任。

相關文章