ShardingSphere


一、简介

1、文档

官网:https://shardingsphere.apache.org/index_zh.html

文档:https://shardingsphere.apache.org/document/5.1.1/cn/overview/

https://shardingsphere.apache.org/document/legacy/4.x/document/cn/features/sharding/use-norms/sql/

Apache ShardingSphere 由 JDBC、Proxy 和 Sidecar(规划中)这 3 款既能够独立部署,又支持混合部署配合使用的产品组成。

2、ShardingSphere-JDBC

程序代码封装

ShardingSphere-JDBC 是 Apache ShardingSphere 的第一个产品,也是 Apache ShardingSphere 的前身。 定位为轻量级 Java 框架,在 Java 的 JDBC 层提供的额外服务。 它使用客户端直连数据库,以 jar 包形式提供服务,无需额外部署和依赖,可理解为增强版的 JDBC 驱动,完全兼容 JDBC 和各种 ORM 框架。

  • 适用于任何基于 JDBC 的 ORM 框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template 或直接使用 JDBC;
  • 支持任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, HikariCP 等;
  • 支持任意实现 JDBC 规范的数据库,目前支持 MySQL,PostgreSQL,Oracle,SQLServer 以及任何可使用 JDBC 访问的数据库。

3、ShardingSphere-Proxy

中间件封装

ShardingSphere-Proxy 是 Apache ShardingSphere 的第二个产品。 它定位为透明化的数据库代理端,提供封装了数据库二进制协议的服务端版本,用于完成对异构语言的支持。 目前提供 MySQL 和 PostgreSQL(兼容 openGauss 等基于 PostgreSQL 的数据库)版本,它可以使用任何兼容 MySQL/PostgreSQL 协议的访问客户端(如:MySQL Command Client, MySQL Workbench, Navicat 等)操作数据,对 DBA 更加友好。

  • 向应用程序完全透明,可直接当做 MySQL/PostgreSQL 使用;
  • 适用于任何兼容 MySQL/PostgreSQL 协议的的客户端。

4、区别

ShardingSphere-JDBC ShardingSphere-Proxy
数据库 任意 MySQL/PostgreSQL
连接消耗数
异构语言 仅 Java 任意
性能 损耗低 损耗略高
无中心化
静态入口
  • ShardingSphere-JDBC 的优势在于对 Java 应用的友好度。
  • ShardingSphere-Proxy 的优势在于对异构语言的支持,以及为 DBA 提供可操作入口。

二、Sharding-JDBC读写分离

1、依赖

<!-- shardingsphere-jdbc 整合 SpringBoot 依赖 -->
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
    <version>5.1.1</version>
</dependency>

<!-- 可整合Mybatis-plus -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.3.1</version>
</dependency>

2、配置读写分离

需要提前搭建主从数据库

修改完配置文件即可,其他操作和一般的 MybatisPlus 项目一致

spring:
  shardingsphere:
    mode:
      # 内存模式
      type: Memory
    props:
      # 打印SQl
      sql-show: true
    datasource:
      # 配置真实数据源
      names: master,slave1
      master:
        driver-class-name: com.mysql.jdbc.Driver
        jdbc-url: jdbc:mysql://127.0.0.1:3306/rewind_db
        type: com.zaxxer.hikari.HikariDataSource
        username: root
        password: root
      slave1:
        driver-class-name: com.mysql.jdbc.Driver
        jdbc-url: jdbc:mysql://127.0.0.1:3307/rewind_db
        type: com.zaxxer.hikari.HikariDataSource
        username: root
        password: root
    rules:
      readwrite-splitting:
        data-sources:
          # 读写分离逻辑数据源名称(自定义)
          myds:
            # 读写分离类型,如: Static,Dynamic
            type: Static
            props:
              # 写库
              write-data-source-name: master
              # 读库,多个逗号分隔
              read-data-source-names: slave1
            # 负载均衡算法(从下面load-balancers中选择)
            load-balancer-name: alg_round
        # 负载均衡算法配置
        load-balancers:
          # 负载均衡算法名称(自定义)
          alg_random:
            # 随机
            type: RANDOM
          alg_round:
            # 轮询
            type: ROUND_ROBIN
          alg_weight:
            # 权重
            type: WEIGHT
            props:
              slave1: 1

3、事务

为了保证主从库间的事务一致性,避免跨服务的分布式事务,ShardingSphere-JDBC的主从模型中,事务中的数据读写均用主库

  • 不添加 @Transactional:insert对主库操作,select对从库操作
  • 添加 @Transactional :则insert和select均对主库操作
  • 注意:在JUnit环境下的 @Transactional 注解,默认情况下就会对事务进行回滚(即使在没加注解@Rollback,也会对事务回滚)

4、测试

boolean save = sysConfigService.save(sysConfig);
List<SysConfig> list = sysConfigService.list();

日志

Actual SQL: master ::: INSERT INTO sys_config  ...
Actual SQL: slave1 ::: SELECT ...

配置详解

(1)运行模式

内存模式(本地测试)

初始化配置或执行 SQL 等造成的元数据结果变更的操作,仅在当前进程中生效。 适用于集成测试的环境启动,方便开发人员在整合功能测试中集成 Apache ShardingSphere 而无需清理运行痕迹。

spring.shardingsphere.mode.type=Memory

单机模式(本地测试)

能够将数据源和规则等元数据信息持久化,但无法将元数据同步至多个 Apache ShardingSphere 实例,无法在集群环境中相互感知。 通过某一实例更新元数据之后,会导致其他实例由于获取不到最新的元数据而产生不一致的错误。 适用于工程师在本地搭建 Apache ShardingSphere 环境。

spring.shardingsphere.mode.type=Standalone
spring.shardingsphere.mode.repository.type= # 持久化仓库类型
spring.shardingsphere.mode.repository.props.<key>= # 持久化仓库所需属性
spring.shardingsphere.mode.overwrite= # 是否使用本地配置覆盖持久化配置

集群模式(生产环境)

提供了多个 Apache ShardingSphere 实例之间的元数据共享和分布式场景下状态协调的能力。 在真实部署上线的生产环境,必须使用集群模式。它能够提供计算能力水平扩展和高可用等分布式系统必备的能力。 集群环境需要通过独立部署的注册中心来存储元数据和协调节点状态。

spring.shardingsphere.mode.type=Cluster
spring.shardingsphere.mode.repository.type= # 持久化仓库类型
spring.shardingsphere.mode.repository.props.namespace= # 注册中心命名空间
spring.shardingsphere.mode.repository.props.server-lists= # 注册中心连接地址
spring.shardingsphere.mode.repository.props.<key>= # 持久化仓库所需属性
spring.shardingsphere.mode.overwrite= # 是否使用本地配置覆盖持久化配置

三、Sharding-JDBC垂直分片

1、基础环境

需要两台及以上的数据库,无需主从,里面有不同的表

ShardingSphere-JDBC远程连接的方式默认的密码加密规则是:mysql_native_password

因此需要在服务器端修改服务器的密码加密规则,如下:

ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';

2、配置垂直分片

spring:
  shardingsphere:
    datasource:
      names: server-user,server-order
      server-order:
        driver-class-name: com.mysql.jdbc.Driver
        jdbc-url: jdbc:mysql://192.168.100.201:3302/db_order
        password: 123456
        type: com.zaxxer.hikari.HikariDataSource
        username: root
      server-user:
        driver-class-name: com.mysql.jdbc.Driver
        jdbc-url: jdbc:mysql://192.168.100.201:3301/db_user
        password: 123456
        type: com.zaxxer.hikari.HikariDataSource
        username: root
    props:
      sql-show: true

    #标准分片表配置(数据节点)
    # spring.shardingsphere.rules.sharding.tables..actual-data-nodes=值
    # 值由数据源名 + 表名组成,以小数点分隔。
    # :逻辑表名
    rules:
      sharding:
        tables:
          t_order:
            actual-data-nodes: server-order.t_order
          t_user:
            actual-data-nodes: server-user.t_user

四、Sharding-JDBC水平分片

1、基础环境

需要两台以上的数据库,无需主从,表结构相同

注意:水平分片的id需要在业务层实现,不能依赖数据库的主键自增

2、基本水平分片配置

spring:
  shardingsphere:
    datasource:
      names: server-user,server-order0,server-order1
      server-order0:
        driver-class-name: com.mysql.jdbc.Driver
        jdbc-url: jdbc:mysql://192.168.100.201:3311/db_order
        password: 123456
        type: com.zaxxer.hikari.HikariDataSource
        username: root
      server-order1:
        driver-class-name: com.mysql.jdbc.Driver
        jdbc-url: jdbc:mysql://192.168.100.201:3310/db_order
        password: 123456
        type: com.zaxxer.hikari.HikariDataSource
        username: root
      server-user:
        driver-class-name: com.mysql.jdbc.Driver
        jdbc-url: jdbc:mysql://192.168.100.201:3301/db_user
        password: 123456
        type: com.zaxxer.hikari.HikariDataSource
        username: root
    rules:
      sharding:
        tables:
          t_order:
            actual-data-nodes: server-order0.t_order0,server-order0.t_order1,server-order1.t_order0,server-order1.t_order1
          t_user:
            actual-data-nodes: server-user.t_user

3、行表达式

优化上一步的分片表配置

https://shardingsphere.apache.org/document/5.1.1/cn/features/sharding/concept/inline-expression/

#========================标准分片表配置(数据节点配置)
# spring.shardingsphere.rules.sharding.tables.<table-name>.actual-data-nodes=值
# 值由数据源名 + 表名组成,以小数点分隔。多个表以逗号分隔,支持 inline 表达式。
# <table-name>:逻辑表名
spring:
  shardingsphere:
    rules:
      sharding:
        tables:
          t_order:
            actual-data-nodes: server-order$->{0..1}.t_order$->{0..1}
          t_user:
            actual-data-nodes: server-user.t_user

行表达式的使用非常直观,只需要在配置中使用 ${ expression }$->{ expression } 标识行表达式即可。 目前支持数据节点和分片算法这两个部分的配置。 行表达式的内容使用的是 Groovy 的语法,Groovy 能够支持的所有操作,行表达式均能够支持。 例如:

${begin..end} 表示范围区间

${[unit1, unit2, unit_x]} 表示枚举值

行表达式中如果出现连续多个 ${ expression }$->{ expression } 表达式,整个表达式最终的结果将会根据每个子表达式的结果进行笛卡尔组合。

例如,以下行表达式:

${['online', 'offline']}_table${1..3}

最终会解析为:

online_table1, online_table2, online_table3, offline_table1, offline_table2, offline_table3

对于均匀分布的数据节点,如果数据结构如下:

db0
  ├── t_order0
  └── t_order1
db1
  ├── t_order0
  └── t_order1

用行表达式可以简化为:

db${0..1}.t_order${0..1}

或者:

db$->{0..1}.t_order$->{0..1}

对于自定义的数据节点,如果数据结构如下:

db0
  ├── t_order0
  └── t_order1
db1
  ├── t_order2
  ├── t_order3
  └── t_order4

用行表达式可以简化为:

db0.t_order${0..1},db1.t_order${2..4}

或者:

db0.t_order$->{0..1},db1.t_order$->{2..4}

4、分片算法配置

(1)水平分库

分片规则:order表中user_id为偶数时,数据插入server-order0服务器user_id为奇数时,数据插入server-order1服务器。这样分片的好处是,同一个用户的订单数据,一定会被插入到同一台服务器上,查询一个用户的订单时效率较高。

spring:
  shardingsphere:
    rules:
      sharding:
        # 分库策略
        tables:
          t_order:
            database-strategy:
              standard:
                # 分片列名称
                sharding-column: user_id
                # 分片算法名称
                sharding-algorithm-name: alg_inline_userid
        # 分片算法配置        
        sharding-algorithms:
          # 行表达式分片算法
          alg_inline_userid:
            type: INLINE
            props:
              algorithm-expression: server-order$->{user_id % 2}
          # 取模分片算法
          alg_mod:
            type: MOD
            props:
              sharding-count: 2

(2)水平分表

分片规则:order表中order_no的哈希值为偶数时,数据插入对应服务器的t_order0表order_no的哈希值为奇数时,数据插入对应服务器的t_order1表。因为order_no是字符串形式,因此不能直接取模。

spring:
  shardingsphere:
    rules:
      sharding:
        tables:
          t_order:
            table-strategy:
              standard:
                sharding-algorithm-name: alg_hash_mod
                sharding-column: order_no
        sharding-algorithms:
          # 哈希取模分片算法
          alg_hash_mod:
            type: HASH_MOD
            props:
              sharding-count: 2

5、分布式序列算法

雪花算法:

https://shardingsphere.apache.org/document/5.1.1/cn/features/sharding/concept/key-generator/

水平分片需要关注全局序列,因为不能简单的使用基于数据库的主键自增。

这里有两种方案:一种是基于MyBatisPlus的id策略;一种是ShardingSphere-JDBC的全局序列配置。

基于MyBatisPlus的id策略:将Order类的id设置成如下形式

@TableId(type = IdType.ASSIGN_ID)
private Long id;

基于 ShardingSphere-JDBC 的全局序列配置:和前面的MyBatisPlus的策略二选一

spring:
  shardingsphere:
    rules:
      sharding:
        tables:
          t_order:
            key-generate-strategy:
              # 分布式序列列名称
              column: id
              # 分布式序列算法名称
              key-generator-name: alg_snowflake
        key-generators:
          alg_snowflake:
            # 分布式序列算法类型
            type: SNOWFLAKE

此时,需要将实体类中的id策略修改成以下形式:

//当配置了shardingsphere-jdbc的分布式序列时,自动使用shardingsphere-jdbc的分布式序列
//当没有配置shardingsphere-jdbc的分布式序列时,自动依赖数据库的主键自增策略
@TableId(type = IdType.AUTO)

6、多表关联

server-order0、server-order1服务器中分别创建两张订单详情表t_order_item0、t_order_item1

我们希望同一个用户的订单表和订单详情表中的数据都在同一个数据源中,避免跨库关联,因此这两张表我们使用相同的分片策略。

那么在t_order_item中我们也需要创建order_nouser_id这两个分片键

CREATE TABLE t_order_item0(
    id BIGINT,
    order_no VARCHAR(30),
    user_id BIGINT,
    price DECIMAL(10,2),
    `count` INT,
    PRIMARY KEY(id)
);

CREATE TABLE t_order_item1(
    id BIGINT,
    order_no VARCHAR(30),
    user_id BIGINT,
    price DECIMAL(10,2),
    `count` INT,
    PRIMARY KEY(id)
);

配置关联表

t_order_item的分片表、分片策略、分布式序列策略和t_order一致

spring:
  shardingsphere:
    rules:
      sharding:
        tables:
          t_order_item:
            # 数据节点配置
            actual-data-nodes: server-order$->{0..1}.t_order_item$->{0..1}
            # 分库策略
            database-strategy:
              standard:
                sharding-algorithm-name: alg_mod
                sharding-column: user_id
            # 分表策略
            table-strategy:
              standard:
                sharding-algorithm-name: alg_hash_mod
                sharding-column: order_no
            # 分布式序列策略配置    
            key-generate-strategy:
              column: id
              key-generator-name: alg_snowflake    

同一个用户的订单表和订单详情表中的数据都在同一个数据源中,避免跨库关联

@Test
public void testInsertOrderAndOrderItem(){

    for (long i = 1; i < 3; i++) {

        Order order = new Order();
        order.setOrderNo("ATGUIGU" + i);
        order.setUserId(1L);
        orderMapper.insert(order);

        for (long j = 1; j < 3; j++) {
            OrderItem orderItem = new OrderItem();
            orderItem.setOrderNo("ATGUIGU" + i);
            orderItem.setUserId(1L);
            orderItem.setPrice(new BigDecimal(10));
            orderItem.setCount(2);
            orderItemMapper.insert(orderItem);
        }
    }

    for (long i = 5; i < 7; i++) {

        Order order = new Order();
        order.setOrderNo("ATGUIGU" + i);
        order.setUserId(2L);
        orderMapper.insert(order);

        for (long j = 1; j < 3; j++) {
            OrderItem orderItem = new OrderItem();
            orderItem.setOrderNo("ATGUIGU" + i);
            orderItem.setUserId(2L);
            orderItem.setPrice(new BigDecimal(1));
            orderItem.setCount(3);
            orderItemMapper.insert(orderItem);
        }
    }

}

7、绑定表

在原来水平分片配置的基础上添加如下配置:

#------------------------绑定表
spring.shardingsphere.rules.sharding.binding-tables[0]=t_order,t_order_item

配置完绑定表后再次进行关联查询的测试:

  • 如果不配置绑定表:测试的结果为8个SQL。多表关联查询会出现笛卡尔积关联。

  • 如果配置绑定表:测试的结果为4个SQL。 多表关联查询不会出现笛卡尔积关联,关联查询效率将大大提升。

绑定表:指分片规则一致的一组分片表。 使用绑定表进行多表关联查询时,必须使用分片键进行关联,否则会出现笛卡尔积关联或跨库关联,从而影响查询效率。

8、广播表

(1)什么是广播表

指所有的分片数据源中都存在的表,表结构及其数据在每个数据库中均完全一致。 适用于数据量不大且需要与海量数据的表进行关联查询的场景,例如:字典表。

广播具有以下特性:

(1)插入、更新操作会实时在所有节点上执行,保持各个分片的数据一致性

(2)查询操作,只从一个节点获取

(3)可以跟任何一个表进行 JOIN 操作

(2)创建广播表

在server-order0、server-order1和server-user服务器中分别创建t_dict表

CREATE TABLE t_dict(
    id BIGINT,
    dict_type VARCHAR(200),
    PRIMARY KEY(id)
);

(3)程序实现

创建实体类

@TableName("t_dict")
@Data
public class Dict {
    //可以使用MyBatisPlus的雪花算法
    @TableId(type = IdType.ASSIGN_ID)
    private Long id;
    private String dictType;
}

创建Mapper

@Mapper
public interface DictMapper extends BaseMapper<Dict> {
}

(4)配置广播表

spring:
  shardingsphere:
    rules:
      sharding:
        # 广播表
        broadcast-tables:
        - t_dict
        tables:
          #数据节点可不配置,默认情况下,向所有数据源广播
          t_dict:
            actual-data-nodes: server-user.t_dict,server-order$->{0..1}.t_dict

(5)测试广播表

@Autowired
private DictMapper dictMapper;

/**
     * 广播表:每个服务器中的t_dict同时添加了新数据
     */
@Test
public void testBroadcast(){

    Dict dict = new Dict();
    dict.setDictType("type1");
    dictMapper.insert(dict);
}

/**
     * 查询操作,只从一个节点获取数据
     * 随机负载均衡规则
     */
@Test
public void testSelectBroadcast(){

    List<Dict> dicts = dictMapper.selectList(null);
    dicts.forEach(System.out::println);
}

五、ShardingSphere-Proxy安装

1、获取

目前 ShardingSphere-Proxy 提供了 3 种获取方式:

2、使用二进制发布包安装

二进制包既可以Linux系统运行,又可以在windows系统运行

step1:解压二进制包

apache-shardingsphere-5.1.1-shardingsphere-proxy-bin.tar.gz

windows:使用解压软件解压文件

Linux:将文件上传至/opt目录,并解压

tar -zxvf apache-shardingsphere-5.1.1-shardingsphere-proxy-bin.tar.gz

step2:MySQL驱动

mysql-connector-java-8.0.22.jar

将MySQl驱动放至解压目录中的ext-lib目录

spte3:修改配置conf/server.yaml

rules:
  - !AUTHORITY
    users:
      - root@%:root
    provider:
      type: ALL_PRIVILEGES_PERMITTED

props:
  sql-show: true

spte4:启动ShardingSphere-Proxy

Linux 操作系统请运行 bin/start.sh

Windows 操作系统请运行 bin/start.bat

指定端口号和配置文件目录:bin/start.bat ${proxy_port} ${proxy_conf_directory}

step5:远程连接ShardingSphere-Proxy

远程访问

mysql -h192.168.100.1 -P3307 -uroot -p

step6:访问测试

show databases;

image-20220819152009158

3、使用Docker安装

step1:启动Docker容器

docker run -d \
-v /atguigu/server/proxy-a/conf:/opt/shardingsphere-proxy/conf \
-v /atguigu/server/proxy-a/ext-lib:/opt/shardingsphere-proxy/ext-lib \
-e ES_JAVA_OPTS="-Xmx256m -Xms256m -Xmn128m" \
-p 3321:3307 \
--name server-proxy-a \
apache/shardingsphere-proxy:5.1.1

step2:上传MySQL驱动

将MySQl驱动上传至/atguigu/server/proxy-a/ext-lib目录

spte3:修改配置server.yaml

rules:
  - !AUTHORITY
    users:
      - root@%:root
    provider:
      type: ALL_PRIVILEGES_PERMITTED

props:
  sql-show: true

将配置文件上传至/atguigu/server/proxy-a/conf目录

spte4:重启容器

docker restart server-proxy-a

step5:远程连接ShardingSphere-Proxy

ShardingSphere-Proxy容器中默认情况下没有mysql命令行客户端的安装,因此需要远程访问

mysql -h192.168.100.201 -P3321 -uroot -p

step6:访问测试

show databases;

image-20220819152009158

常见问题:docker容器无法远程连接

容器可以成功的创建并启动,但是无法远程连接。排除防火墙和网络等问题后,看看是不是因为容器内存不足导致。

原因:容器可分配内存不足

查看办法:进入容器后查看ShardingSphere-Proxy的日志,如有有cannot allocate memory,则说明容器内存不足

docker exec -it server-proxy-a env LANG=C.UTF-8 /bin/bash
cd /opt/shardingsphere-proxy/logs
tail stdout.log 

image-20220819151154763

解决方案:创建容器的时候使用JVM参数

-e ES_JAVA_OPTS="-Xmx256m -Xms256m -Xmn128m"

六、ShardingSphere-Proxy读写分离

1、修改配置文件

修改配置config-readwrite-splitting.yaml

schemaName: readwrite_splitting_db

dataSources:
  write_ds:
    url: jdbc:mysql://192.168.100.201:3306/db_user?serverTimezone=UTC&useSSL=false
    username: root
    password: 123456
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1
  read_ds_0:
    url: jdbc:mysql://192.168.100.201:3307/db_user?serverTimezone=UTC&useSSL=false
    username: root
    password: 123456
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1
  read_ds_1:
    url: jdbc:mysql://192.168.100.201:3308/db_user?serverTimezone=UTC&useSSL=false
    username: root
    password: 123456
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1

rules:
- !READWRITE_SPLITTING
  dataSources:
    readwrite_ds:
      type: Static
      props:
        write-data-source-name: write_ds
        read-data-source-names: read_ds_0,read_ds_1

将配置文件上传至/atguigu/server/proxy-a/conf目录

重启容器

docker restart server-proxy-a

2、实时查看日志

可以通过这种方式查看服务器中输出的SQL语句

docker exec -it server-proxy-a env LANG=C.UTF-8 /bin/bash
tail -f /opt/shardingsphere-proxy/logs/stdout.log 

3、远程访问测试

mysql> show databases;
mysql> use readwrite_splitting_db;
mysql> show tables;
mysql> select * from t_user;
mysql> select * from t_user;
mysql> insert into t_user(uname) values('wang5');

4、应用程序访问Proxy

4.1、创建项目

项目类型:Spring Initializr

SpringBoot脚手架:http://start.aliyun.com

项目名:sharding-proxy-demo

SpringBoot版本:2.3.7.RELEASE

4.2、添加依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>

    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.3.1</version>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>

4.3、创建实体类

package com.atguigu.shardingproxydemo.entity;

@TableName("t_user")
@Data
public class User {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String uname;
}

4.4、创建Mapper

package com.atguigu.shardingproxydemo.mapper;

@Mapper
public interface UserMapper extends BaseMapper<User> {
}

4.5、配置数据源

# 应用名称
spring.application.name=sharding-proxy-demo
# 开发环境设置
spring.profiles.active=dev

#mysql数据库连接(proxy)
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://192.168.100.201:3321/readwrite_splitting_db?serverTimezone=GMT%2B8&useSSL=false
spring.datasource.username=root
spring.datasource.password=root

#mybatis日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

4.6、测试

package com.atguigu.shardingproxydemo;

@SpringBootTest
class ShardingProxyDemoApplicationTests {

    @Autowired
    private UserMapper userMapper;

    /**
     * 读数据测试
     */
    @Test
    public void testSelectAll(){
        List<User> users = userMapper.selectList(null);
        users.forEach(System.out::println);
    }
}

七、ShardingSphere-Proxy垂直分片

1、修改配置文件

修改配置config-sharding.yaml

schemaName: sharding_db

dataSources:
  ds_0:
    url: jdbc:mysql://192.168.100.201:3301/db_user?serverTimezone=UTC&useSSL=false
    username: root
    password: 123456
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1
  ds_1:
    url: jdbc:mysql://192.168.100.201:3302/db_order?serverTimezone=UTC&useSSL=false
    username: root
    password: 123456
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1

rules:
- !SHARDING
  tables:
    t_user:
      actualDataNodes: ds_0.t_user
    t_order:
      actualDataNodes: ds_1.t_order

2、实时查看日志

可以通过这种方式查看服务器中输出的SQL语句

docker exec -it server-proxy-a env LANG=C.UTF-8 /bin/bash
tail -f /opt/shardingsphere-proxy/logs/stdout.log 

3、远程访问测试

mysql> show databases;
mysql> use sharding_db;
mysql> show tables;
mysql> select * from t_order;
mysql> select * from t_user;

八、ShardingSphere-Proxy水平分片

1、修改配置文件

修改配置config-sharding.yaml

schemaName: sharding_db

dataSources:
  ds_user:
    url: jdbc:mysql://192.168.100.201:3301/db_user?serverTimezone=UTC&useSSL=false
    username: root
    password: 123456
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1
  ds_order0:
    url: jdbc:mysql://192.168.100.201:3310/db_order?serverTimezone=UTC&useSSL=false
    username: root
    password: 123456
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1
  ds_order1:
    url: jdbc:mysql://192.168.100.201:3311/db_order?serverTimezone=UTC&useSSL=false
    username: root
    password: 123456
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1

rules:
- !SHARDING
  tables:
    t_user:
      actualDataNodes: ds_user.t_user

    t_order:
      actualDataNodes: ds_order${0..1}.t_order${0..1}
      databaseStrategy:
        standard:
          shardingColumn: user_id
          shardingAlgorithmName: alg_mod
      tableStrategy:
        standard:
          shardingColumn: order_no
          shardingAlgorithmName: alg_hash_mod
      keyGenerateStrategy:
        column: id
        keyGeneratorName: snowflake
    t_order_item:
      actualDataNodes: ds_order${0..1}.t_order_item${0..1}
      databaseStrategy:
        standard:
          shardingColumn: user_id
          shardingAlgorithmName: alg_mod
      tableStrategy:
        standard:
          shardingColumn: order_no
          shardingAlgorithmName: alg_hash_mod
      keyGenerateStrategy:
        column: id
        keyGeneratorName: snowflake

  bindingTables:
    - t_order,t_order_item


  broadcastTables:
    - t_dict

  shardingAlgorithms:
    alg_inline_userid:
      type: INLINE
      props:
        algorithm-expression: server-order$->{user_id % 2}
    alg_mod:
      type: MOD
      props:
        sharding-count: 2
    alg_hash_mod:
      type: HASH_MOD
      props:
        sharding-count: 2

  keyGenerators:
    snowflake:
      type: SNOWFLAKE

2、实时查看日志

可以通过这种方式查看服务器中输出的SQL语句

docker exec -it server-proxy-a env LANG=C.UTF-8 /bin/bash
tail -f /opt/shardingsphere-proxy/logs/stdout.log 

3、远程访问测试

mysql> show databases;
mysql> use sharding_db;
mysql> show tables;
mysql> select * from t_order; --测试水平分片
mysql> select * from t_dict; --测试广播表

  目录