文章目錄
- 一、Sharding-JDBC介紹
-
- 1. Sharding-JDBC介紹
- 2. Sharding-JDBC與JDBC性能對比
- 二、Sharding-JDBC快速入門
-
- 1. 需求說明
- 2. 環境搭建
-
- 2.1 環境說明
- 2.2 建立資料庫
- 2.3 引入maven依賴
- 3. 編寫程式
-
- 3.1 分片規則配置
- 3.2.資料操作
- 3.3.測試
- 4. 流程分析
- 5. 其他內建方式
-
- 5.1 Spring Boot properties配置
- 5.2 Spring Boot Yaml 配置
- 5.3 Java 配置
- 5.4 Spring命名空間配置
一、Sharding-JDBC介紹
1. Sharding-JDBC介紹
Sharding-JDBC是當當網研發的開源分布式資料庫中間件,從 3.0 開始Sharding-JDBC被包含在 Sharding-Sphere 中,之後該項目進入Apache孵化器,4.0版本之後的版本為Apache版本。
ShardingSphere是一套開源的分布式資料庫中間件解決方案組成的生态圈,它由Sharding-JDBC、Sharding- Proxy和Sharding-Sidecar(計劃中)這3款互相獨立的産品組成。 他們均提供标準化的資料分片、分布式事務和資料庫治理功能,可适用于如Java同構、異構語言、容器、雲原生等各種多樣化的應用場景。
官方位址:https://shardingsphere.apache.org/document/current/cn/overview/
目前隻需關注Sharding-JDBC,它定位為輕量級Java架構,在Java的JDBC層提供的額外服務。 它使用用戶端直連資料庫,以jar包形式提供服務,無需額外部署和依賴,可了解為增強版的JDBC驅動,完全相容JDBC和各種ORM架構。
Sharding-JDBC的核心功能為資料分片和讀寫分離,通過Sharding-JDBC,應用可以透明的使用jdbc通路已經分庫分表、讀寫分離的多個資料源,而不用關心資料源的數量以及資料如何分布。
- 适用于任何基于Java的ORM架構,如: Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC。
- 基于任何第三方的資料庫連接配接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP等。
- 支援任意實作JDBC規範的資料庫。目前支援MySQL,Oracle,SQLServer和PostgreSQL。

上圖展示了Sharding-Jdbc的工作方式,使用Sharding-Jdbc前需要人工對資料庫進行分庫分表,在應用程式中加入Sharding-Jdbc的Jar包,應用程式通過Sharding-Jdbc操作分庫分表後的資料庫和資料表,由于Sharding-Jdbc是對Jdbc驅動的增強,使用Sharding-Jdbc就像使用Jdbc驅動一樣,在應用程式中是無需指定具體要操作的分庫和分表的。
2. Sharding-JDBC與JDBC性能對比
①性能損耗測試:伺服器資源充足、并發數相同,比較JDBC和Sharding-JDBC性能損耗,Sharding-JDBC相對JDBC損耗不超過7%。
②性能對比測試:伺服器資源使用到極限,相同的場景JDBC與Sharding-JDBC的吞吐量相當。
③性能對比測試:伺服器資源使用到極限,Sharding-JDBC采用分庫分表後,Sharding-JDBC吞吐量較JDBC不分表有接近2倍的提升。
二、Sharding-JDBC快速入門
1. 需求說明
本章節使用Sharding-JDBC完成對訂單表的水準分表,通過快速入門程式的開發,快速體驗Sharding-JDBC的使用方法。
人工建立兩張表,t_order_1和t_order_2,這兩張表是訂單表拆分後的表,通過Sharding-Jdbc向訂單表插入資料,按照一定的分片規則,主鍵為偶數的進入t_order_1,另一部分資料進入t_order_2,通過Sharding-Jdbc查詢資料,根據SQL語句的内容從t_order_1或t_order_2查詢資料。
2. 環境搭建
2.1 環境說明
- 作業系統:Win10
- 資料庫:MySQL-5.7.25
- JDK:64位 jdk1.8.0_201
- 應用架構:spring-boot-2.1.3.RELEASE,Mybatis3.5.0
- Sharding-JDBC:sharding-jdbc-spring-boot-starter-4.0.0-RC1
2.2 建立資料庫
建立訂單庫order_db
CREATE DATABASE order_db
CHARACTER SET ‘utf8’ COLLATE ‘utf8_general_ci’;
在order_db中建立t_order_1、t_order_2表
DROP TABLE IF EXISTS
t_order_1
;
CREATE TABLE
(
t_order_1
bigint(20) NOT NULL COMMENT ‘訂單id’,
order_id
decimal(10, 2) NOT NULL COMMENT ‘訂單價格’,
price
bigint(20) NOT NULL COMMENT ‘下單使用者id’,
user_id
status
varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT ‘訂單狀态’,
PRIMARY KEY (
order_id
) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
DROP TABLE IF EXISTS
t_order_2
;
CREATE TABLE
(
t_order_2
bigint(20) NOT NULL COMMENT ‘訂單id’,
order_id
decimal(10, 2) NOT NULL COMMENT ‘訂單價格’,
price
bigint(20) NOT NULL COMMENT ‘下單使用者id’,
user_id
status
varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT ‘訂單狀态’,
PRIMARY KEY (
order_id
) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
2.3 引入maven依賴
引入 sharding-jdbc和SpringBoot整合的Jar包:
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding‐jdbc‐spring‐boot‐starter</artifactId>
<version>4.0.0‐RC1</version>
</dependency>
3. 編寫程式
3.1 分片規則配置
分片規則配置是sharding-jdbc進行對分庫分表操作的重要依據,配置内容包括:資料源、主鍵生成政策、分片政策等。
在application.properties中配置:
server.port=56081
#工程名
spring.application.name = sharding-jdbc-simple-demo
#通路路徑
server.servlet.context-path = /sharding-jdbc-simple-demo
spring.http.encoding.enabled = true
spring.http.encoding.charset = UTF-8
spring.http.encoding.force = true
#覆寫重複的bean定義
spring.main.allow-bean-definition-overriding = true
#mybatis駝峰命名
mybatis.configuration.map-underscore-to-camel-case = true
#sharding-jdbc分片規則配置
#資料源,自定義名稱m1
spring.shardingsphere.datasource.names = m1
spring.shardingsphere.datasource.m1.type = com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m1.driver-class-name = com.mysql.jdbc.Driver
spring.shardingsphere.datasource.m1.url = jdbc:mysql://localhost:3306/order_db?useUnicode=true
spring.shardingsphere.datasource.m1.username = root
spring.shardingsphere.datasource.m1.password = root
# 指定t_order表的資料分布情況,配置資料節點,邏輯表t_order對應的節點是:m1.t_order_1,m1.t_order_2
spring.shardingsphere.sharding.tables.t_order.actual-data-nodes = m1.t_order_$->{1..2}
# 指定t_order表的主鍵生成政策為SNOWFLAKE,主鍵為order_id
spring.shardingsphere.sharding.tables.t_order.key-generator.column=order_id
spring.shardingsphere.sharding.tables.t_order.key-generator.type=SNOWFLAKE
# 指定t_order表的分片政策,分片政策包括分片鍵和分片算法
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 + 1}
# 打開sql輸出日志
spring.shardingsphere.props.sql.show = true
swagger.enable = true
logging.level.root = info
logging.level.org.springframework.web = info
logging.level.com.itheima.dbsharding = debug
logging.level.druid.sql = debug
1.首先定義資料源m1,并對m1進行實際的參數配置。
2.指定t_order表的資料分布情況,分布在m1.t_order_1,m1.t_order_2
3.指定t_order表的主鍵生成政策為SNOWFLAKE,SNOWFLAKE是一種分布式自增算法,保證id全局唯一
4.定義t_order分片政策,order_id為偶數的資料落在t_order_1,為奇數的落在t_order_2,分表政策的表達式為 t_order_$->{order_id % 2 + 1}
3.2.資料操作
@Mapper
@Component
public interface OrderDao {
/**
* 插入訂單
*/
@Insert("insert into t_order(price,user_id,status)values(#{price},#{userId},#{status})")
int insertOrder(@Param("price")BigDecimal price,@Param("userId")Long userId,@Param("status")String status);
/**
* 根據id清單查詢訂單
*/
@Select("<script>" +
"select" +
" * " +
" from t_order t " +
" where t.order_id in " +
" <foreach collection='orderIds' open='(' separator=',' close=')' item='id'>" +
" #{id} " +
" </foreach>" +
"</script>")
List<Map> selectOrderbyIds(@Param("orderIds") List<Long> orderIds);
}
3.3.測試
①編寫單元測試:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {ShardingJdbcSimpleBootstrap.class})
public class OrderDaoTest {
@Autowired
OrderDao orderDao;
@Test
public void testInsertOrder() {
for (int i = 1; i < 20; i++) {
orderDao.insertOrder(new BigDecimal(i), 1L, "SUCCESS");
}
}
@Test
public void testSelectOrderbyIds() {
List<Long> ids = new ArrayList<>();
ids.add(373897739357913088L);
ids.add(373897037306920961L);
List<Map> maps = orderDao.selectOrderbyIds(ids);
System.out.println(maps);
}
}
②執行testInsertOrder:
通過日志可以發現order_id為奇數的被插入到t_order_2表,為偶數的被插入到t_order_1表,達到預期目标。
③執行testSelectOrderbyIds:
通過日志可以發現,根據傳入order_id的奇偶不同,sharding-jdbc分别去不同的表檢索資料,達到預期目标。
4. 流程分析
通過日志分析,Sharding-JDBC在拿到使用者要執行的sql之後幹了哪些事兒:
(1)解析sql,擷取分片鍵值,在本例中是order_id
(2)Sharding-JDBC通過規則配置 t_order_$->{order_id % 2 + 1},知道了當order_id為偶數時,應該往 t_order_1表插資料,為奇數時,往t_order_2插資料。
(3)于是Sharding-JDBC根據order_id的值改寫sql語句,改寫後的SQL語句是真實所要執行的SQL語句。
(4)執行改寫後的真實sql語句
(5)将所有真正執行sql的結果進行彙總合并,傳回。
5. 其他內建方式
Sharding-JDBC不僅可以與spring boot良好內建,它還支援其他配置方式,共支援以下四種內建方式。
5.1 Spring Boot properties配置
#sharding-jdbc分片規則配置
#資料源,自定義名稱m1
spring.shardingsphere.datasource.names = m1
spring.shardingsphere.datasource.m1.type = com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m1.driver-class-name = com.mysql.jdbc.Driver
spring.shardingsphere.datasource.m1.url = jdbc:mysql://localhost:3306/order_db?useUnicode=true
spring.shardingsphere.datasource.m1.username = root
spring.shardingsphere.datasource.m1.password = root
# 指定t_order表的資料分布情況,配置資料節點,邏輯表t_order對應的節點是:m1.t_order_1,m1.t_order_2
spring.shardingsphere.sharding.tables.t_order.actual-data-nodes = m1.t_order_$->{1..2}
# 指定t_order表的主鍵生成政策為SNOWFLAKE,主鍵為order_id
spring.shardingsphere.sharding.tables.t_order.key-generator.column=order_id
spring.shardingsphere.sharding.tables.t_order.key-generator.type=SNOWFLAKE
# 指定t_order表的分片政策,分片政策包括分片鍵和分片算法
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 + 1}
5.2 Spring Boot Yaml 配置
定義application.yml,内容如下:
server:
port: 56081
servlet:
context-path: /sharding-jdbc-simple-demo
spring:
application:
name: sharding-jdbc-simple-demo
http:
encoding:
enabled: true
charset: utf-8
force: true
main:
allow-bean-definition-overriding: true
shardingsphere:
datasource:
names: m1
m1:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/order_db?useUnicode=true
username: root
password: root
sharding:
tables:
t_order:
actualDataNodes: m1.t_order_$->{1..2}
tableStrategy:
inline:
shardingColumn: order_id
algorithmExpression: t_order_$->{order_id % 2 + 1}
keyGenerator:
type: SNOWFLAKE
column: order_id
props:
sql:
show: true
mybatis:
configuration:
map-underscore-to-camel-case: true
swagger:
enable: true
logging:
level:
root: info
org.springframework.web: info
com.itheima.dbsharding: debug
druid.sql: debug
5.3 Java 配置
添加配置類:
@Configuration
public class ShardingJdbcConfig {
// 配置分片規則
// 定義資料源
Map<String, DataSource> createDataSourceMap() {
DruidDataSource dataSource1 = new DruidDataSource();
dataSource1.setDriverClassName("com.mysql.jdbc.Driver");
dataSource1.setUrl("jdbc:mysql://localhost:3306/order_db?useUnicode=true");
dataSource1.setUsername("root");
dataSource1.setPassword("root");
Map<String, DataSource> result = new HashMap<>();
result.put("m1", dataSource1);
return result;
}
// 定義主鍵生成政策
private static KeyGeneratorConfiguration getKeyGeneratorConfiguration() {
KeyGeneratorConfiguration result = new KeyGeneratorConfiguration("SNOWFLAKE","order_id");
return result;
}
// 定義t_order表的分片政策
TableRuleConfiguration getOrderTableRuleConfiguration() {
TableRuleConfiguration result = new TableRuleConfiguration("t_order","m1.t_order_$->{1..2}");
result.setTableShardingStrategyConfig(new InlineShardingStrategyConfiguration("order_id", "t_order_$->{order_id % 2 + 1}"));
result.setKeyGeneratorConfig(getKeyGeneratorConfiguration());
return result;
}
// 定義sharding-Jdbc資料源
@Bean
DataSource getShardingDataSource() throws SQLException {
ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
shardingRuleConfig.getTableRuleConfigs().add(getOrderTableRuleConfiguration());
//spring.shardingsphere.props.sql.show = true
Properties properties = new Properties();
properties.put("sql.show","true");
return ShardingDataSourceFactory.createDataSource(createDataSourceMap(), shardingRuleConfig,properties);
}
}
注意:
Sharding-Jdbc與SpringBoot內建,會自動從配置檔案中讀“spring.shardingsphere”字首的配置
由于使用java配置類方式,沒有配置檔案,讀取不到就會報以上錯誤
此時需要在啟動類中加上@SpringBootApplication(exclude = SpringBootConfiguration.class)
import org.apache.shardingsphere.shardingjdbc.spring.boot.SpringBootConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(exclude = SpringBootConfiguration.class)
public class ShardingJdbcSimpleBootstrap {
public static void main(String[] args) {
SpringApplication.run(ShardingJdbcSimpleBootstrap.class, args);
}
}
5.4 Spring命名空間配置
此方式使用xml方式配置,不推薦使用。
<?xml version="1.0" encoding="UTF‐8"?>
<?xml version="1.0" encoding="UTF‐8"?>
xmlns:xsi="http://www.w3.org/2001/XMLSchema‐instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context" 、
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:sharding="http://shardingsphere.apache.org/schema/shardingsphere/sharding"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring‐beans.xsd
http://shardingsphere.apache.org/schema/shardingsphere/sharding
http://shardingsphere.apache.org/schema/shardingsphere/sharding/sharding.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring‐context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring‐tx.xsd">
<context:annotation‐config />
<!‐‐定義多個資料源‐‐>
<bean id="m1" class="com.alibaba.druid.pool.DruidDataSource" destroy‐method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/order_db_1?useUnicode=true" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
<!‐‐定義分庫政策‐‐>
<sharding:inline‐strategy id="tableShardingStrategy" sharding‐column="order_id" algorithm‐ expression="t_order_$‐>{order_id % 2 + 1}" />
<!‐‐定義主鍵生成政策‐‐>
<sharding:key‐generator id="orderKeyGenerator" type="SNOWFLAKE" column="order_id" />
<!‐‐定義sharding‐Jdbc資料源‐‐>
<sharding:data‐source id="shardingDataSource">
<sharding:sharding‐rule data‐source‐names="m1">
<sharding:table‐rules>
<sharding:table‐rule logic‐table="t_order" table‐strategy‐ ref="tableShardingStrategy" key‐generator‐ref="orderKeyGenerator" />
</sharding:table‐rules>
</sharding:sharding‐rule>
</sharding:data‐source>
</beans>