ShardingSphere分庫分表實(shí)戰(zhàn)(一) 基礎(chǔ)環(huán)境搭建

一、ShardingSphere簡介

Apache ShardingSphere 是一套開源的分布式數(shù)據(jù)庫解決方案組成的生態(tài)圈,它由 JDBC、Proxy 和 Sidecar(規(guī)劃中)這 3 款既能夠獨(dú)立部署,又支持混合部署配合使用的產(chǎn)品組成。 它們均提供標(biāo)準(zhǔn)化的數(shù)據(jù)水平擴(kuò)展、分布式事務(wù)和分布式治理等功能,可適用于如 Java 同構(gòu)、異構(gòu)語言、云原生等各種多樣化的應(yīng)用場景。

以下是Sharding Sphere在Github上的star數(shù):


image.png

Apache ShardingSphere 旨在充分合理地在分布式的場景下利用關(guān)系型數(shù)據(jù)庫的計(jì)算和存儲能力,而并非實(shí)現(xiàn)一個全新的關(guān)系型數(shù)據(jù)庫。 關(guān)系型數(shù)據(jù)庫當(dāng)今依然占有巨大市場份額,是企業(yè)核心系統(tǒng)的基石,未來也難于撼動,我們更加注重在原有基礎(chǔ)上提供增量,而非顛覆。


image.png

Apache ShardingSphere 5.x 版本開始致力于可插拔架構(gòu),項(xiàng)目的功能組件能夠靈活的以可插拔的方式進(jìn)行擴(kuò)展。 目前,數(shù)據(jù)分片、讀寫分離、數(shù)據(jù)加密、影子庫壓測等功能,以及 MySQL、PostgreSQL、SQLServer、Oracle 等 SQL 與協(xié)議的支持,均通過插件的方式織入項(xiàng)目。 開發(fā)者能夠像使用積木一樣定制屬于自己的獨(dú)特系統(tǒng)。Apache ShardingSphere 目前已提供數(shù)十個 SPI 作為系統(tǒng)的擴(kuò)展點(diǎn),仍在不斷增加中。

Sharding-JDBC

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


image.png

適用于任何基于 JDBC 的 ORM 框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template 或直接使用 JDBC。
支持任何第三方的數(shù)據(jù)庫連接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP 等。
支持任意實(shí)現(xiàn) JDBC 規(guī)范的數(shù)據(jù)庫,目前支持 MySQL,Oracle,SQLServer,PostgreSQL 以及任何遵循 SQL92 標(biāo)準(zhǔn)的數(shù)據(jù)庫。

Sharding-Proxy

定位為透明化的數(shù)據(jù)庫代理端,提供封裝了數(shù)據(jù)庫二進(jìn)制協(xié)議的服務(wù)端版本,用于完成對異構(gòu)語言的支持。 目前提供 MySQL 和 PostgreSQL 版本,它可以使用任何兼容 MySQL/PostgreSQL 協(xié)議的訪問客戶端(如:MySQL Command Client, MySQL Workbench, Navicat 等)操作數(shù)據(jù),對 DBA 更加友好。


image.png

向應(yīng)用程序完全透明,可直接當(dāng)做 MySQL/PostgreSQL 使用。
適用于任何兼容 MySQL/PostgreSQL 協(xié)議的的客戶端。

二、ShardingJDBC實(shí)戰(zhàn)

2.1 基礎(chǔ)環(huán)境搭建

springboot整合mybatis-plus為例,添加依賴

        <!--mybatis-plus依賴-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version>
        </dependency>
        <!--sharding-jdbc依賴-->
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
            <version>4.1.1</version>
        </dependency>
        <!--分布式事務(wù)XA支持-->
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-transaction-xa-core</artifactId>
            <version>4.1.1</version>
        </dependency>

其中,sharding-transaction-xa-core是分布式事務(wù)的支持,如果不需要使用XA做分布式事務(wù),則可以不用添加。

數(shù)據(jù)庫

image.png

2.1.1 數(shù)據(jù)源配置

#打印sql
spring.shardingsphere.props.sql.show=true
#datasource
spring.shardingsphere.datasource.names=ds0,ds1

spring.shardingsphere.datasource.ds0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds0.jdbc-url=jdbc:mysql://localhost:3306/heima1?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.shardingsphere.datasource.ds0.username=root
spring.shardingsphere.datasource.ds0.password=123456

spring.shardingsphere.datasource.ds1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds1.jdbc-url=jdbc:mysql://localhost:3306/heima2?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.shardingsphere.datasource.ds1.username=root
spring.shardingsphere.datasource.ds1.password=123456

spring.shardingsphere.datasource.names指定當(dāng)前的數(shù)據(jù)源名稱,比如這里的ds0、ds1就是配置了兩個數(shù)據(jù)源。然后接下來分別對兩個數(shù)據(jù)源配置如下幾個內(nèi)容

  • type數(shù)據(jù)庫連接池
  • driver-class-name數(shù)據(jù)庫驅(qū)動
  • jdbc-url數(shù)據(jù)庫連接地址
  • username賬號名稱
  • password密碼

2.1.2 分庫配置

#sharding-database
spring.shardingsphere.sharding.tables.position.database-strategy.inline.sharding-column=id
spring.shardingsphere.sharding.tables.position.database-strategy.inline.algorithm-expression=ds$->{id % 2}

這里提到一個關(guān)鍵詞inline行表達(dá)式,行表達(dá)式的使用非常直觀,只需要在配置中使用 ${ expression }$->{ expression }標(biāo)識行表達(dá)式即可。 行表達(dá)式的內(nèi)容使用的是 Groovy 的語法,Groovy 能夠支持的所有操作,行表達(dá)式均能夠支持。例如:

  • ${begin..end} 表示范圍區(qū)間
  • ${[unit1, unit2, unit_x]}表示枚舉值

所以上述sharding-column=id指的是指定當(dāng)前分庫時需要依賴的分片鍵是id,algorithm-expression=ds$->{id % 2}指的是分片算法是將id取模之后,和ds進(jìn)行拼接:
比如查詢的id如果是1000,1000在對2取模之后會變成ds0,然后sql語句就會去ds0這個數(shù)據(jù)源中執(zhí)行。

2.1.3 實(shí)體類定義

package com.brianxia.shardingjdbcmybatis.entity;

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import javax.persistence.*;
import java.io.Serializable;

@TableName("position")
@Data
public class Position implements Serializable {

    @TableId(value = "id",type = IdType.INPUT)
    private Long id;
    private String name;
    private String salary;
    private String city;
   
}

2.1.4 mapper接口添加

package com.brianxia.shardingjdbcmybatis.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.brianxia.shardingjdbcmybatis.entity.BOrder;
import com.brianxia.shardingjdbcmybatis.entity.Position;
import org.apache.ibatis.annotations.Mapper;

/**
 * @author brianxia
 * @version 1.0
 * @date 2021/5/25 15:41
 */
@Mapper
public interface PositionMapper extends BaseMapper<Position> {
}

三、 測試

package com.brianxia.shardingjdbcmybatis;

import com.brianxia.shardingjdbcmybatis.entity.Position;
import com.brianxia.shardingjdbcmybatis.mapper.PositionMapper;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

/**
 * @author brianxia
 * @version 1.0
 * @date 2021/5/27 18:45
 */
@SpringBootTest
public class BaseTest {

    @Autowired
    private PositionMapper positionMapper;


    @Test
    public void add(){
        for (long i = 0; i < 100; i++) {
            Position position = new Position();
            position.setId(i);
            positionMapper.insert(position);
        }
    }
}

首先使用自定義的id進(jìn)行數(shù)據(jù)庫的插入,執(zhí)行日志:

2021-05-27 18:49:42.394  INFO 21560 --- [           main] ShardingSphere-SQL                       : Logic SQL: INSERT INTO position  ( id )  VALUES  ( ? )
2021-05-27 18:49:42.394  INFO 21560 --- [           main] ShardingSphere-SQL                       : SQLStatement: InsertStatementContext(super=CommonSQLStatementContext(sqlStatement=org.apache.shardingsphere.sql.parser.sql.statement.dml.InsertStatement@20c3b34b, tablesContext=org.apache.shardingsphere.sql.parser.binder.segment.table.TablesContext@ff21443), tablesContext=org.apache.shardingsphere.sql.parser.binder.segment.table.TablesContext@ff21443, columnNames=[id], insertValueContexts=[InsertValueContext(parametersCount=1, valueExpressions=[ParameterMarkerExpressionSegment(startIndex=40, stopIndex=40, parameterMarkerIndex=0)], parameters=[97])], generatedKeyContext=Optional[GeneratedKeyContext(columnName=id, generated=false, generatedValues=[97])])
2021-05-27 18:49:42.394  INFO 21560 --- [           main] ShardingSphere-SQL                       : Actual SQL: ds1 ::: INSERT INTO position  ( id )  VALUES  (?) ::: [97]
2021-05-27 18:49:42.398  INFO 21560 --- [           main] ShardingSphere-SQL                       : Logic SQL: INSERT INTO position  ( id )  VALUES  ( ? )
2021-05-27 18:49:42.398  INFO 21560 --- [           main] ShardingSphere-SQL                       : SQLStatement: InsertStatementContext(super=CommonSQLStatementContext(sqlStatement=org.apache.shardingsphere.sql.parser.sql.statement.dml.InsertStatement@20c3b34b, tablesContext=org.apache.shardingsphere.sql.parser.binder.segment.table.TablesContext@6253e59a), tablesContext=org.apache.shardingsphere.sql.parser.binder.segment.table.TablesContext@6253e59a, columnNames=[id], insertValueContexts=[InsertValueContext(parametersCount=1, valueExpressions=[ParameterMarkerExpressionSegment(startIndex=40, stopIndex=40, parameterMarkerIndex=0)], parameters=[98])], generatedKeyContext=Optional[GeneratedKeyContext(columnName=id, generated=false, generatedValues=[98])])
2021-05-27 18:49:42.398  INFO 21560 --- [           main] ShardingSphere-SQL                       : Actual SQL: ds0 ::: INSERT INTO position  ( id )  VALUES  (?) ::: [98]
2021-05-27 18:49:42.402  INFO 21560 --- [           main] ShardingSphere-SQL                       : Logic SQL: INSERT INTO position  ( id )  VALUES  ( ? )
2021-05-27 18:49:42.402  INFO 21560 --- [           main] ShardingSphere-SQL                       : SQLStatement: InsertStatementContext(super=CommonSQLStatementContext(sqlStatement=org.apache.shardingsphere.sql.parser.sql.statement.dml.InsertStatement@20c3b34b, tablesContext=org.apache.shardingsphere.sql.parser.binder.segment.table.TablesContext@12f8682a), tablesContext=org.apache.shardingsphere.sql.parser.binder.segment.table.TablesContext@12f8682a, columnNames=[id], insertValueContexts=[InsertValueContext(parametersCount=1, valueExpressions=[ParameterMarkerExpressionSegment(startIndex=40, stopIndex=40, parameterMarkerIndex=0)], parameters=[99])], generatedKeyContext=Optional[GeneratedKeyContext(columnName=id, generated=false, generatedValues=[99])])
2021-05-27 18:49:42.402  INFO 21560 --- [           main] ShardingSphere-SQL                       : Actual SQL: ds1 ::: INSERT INTO position  ( id )  VALUES  (?) ::: [99]

可以看到,奇數(shù)的id已經(jīng)被送到了ds1庫中,偶數(shù)的id被送到了dis0庫中。

image.png

四、 總結(jié)

通過簡單的配置ShardingSphere已經(jīng)完成了分庫操作,下一小節(jié)中我們會使用ShardingSphere進(jìn)行分庫+分表,同時解決主鍵ID生成的問題。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容