Sharding-Sphere 核心功能使用

什么是Sharding-Sphere

  1. 一套开源的分布式数据库中间件解决方案
    2、有三个产品:Sharding-JDBC 和 Sharding-Proxy
    3、定位为关系型数据库中间件,合理在分布式环境下使用关系型数据库操作

    什么是分库分表

    1、数据库数据量不可控的,随着时间和业务发展,造成表里面数据越来越多,如果再去对数 据库表 curd 操作时候,造成性能问题。
    2、方案
    1:从硬件上
    3、方案
    2:分库分表
    为了解决由于数据量过大而造成数据库性能降低问题
    Sharding-Sphere 核心功能使用 - 图1

    分库分表的策略

  2. 垂直拆分
    a. 垂直分表:操作数据库中某张表,把这张表中一部分字段数据存到一张新表里面,再把这张表另一 部分字段数据存到另外一张表里面(即将一个表的字段分散到不同的表去)
    Sharding-Sphere 核心功能使用 - 图2
    b.垂直分库:把单一数据库按照业务进行划分,不同的业务专门的数据库。
    Sharding-Sphere 核心功能使用 - 图3
    2. 水平拆分
    a. 水平分表:在同一个数据库中,相同结构的表具有多张
    Sharding-Sphere 核心功能使用 - 图4
    b.水平分库:
    Sharding-Sphere 核心功能使用 - 图5
    分库分表的应用和产生的问题
    应用:
    (1)在数据库设计时候考虑垂直分库和垂直分表
    (2)随着数据库数据量增加,不要马上考虑做水平切分,首先考虑缓存处理,读写分离,使 用索引等等方式,如果这些方式不能根本解决问题了,再考虑做水平分库和水平分表
    问题:
    (1)跨节点连接查询问题(分页、排序)
    (2)多数据源管理问题
    什么是Sharding-JDBC
    1、是轻量级的 java 框架,是增强版的 JDBC 驱动
    2、Sharding-JDBC
    (1)主要目的是:简化对分库分表之后数据相关操作
    Sharding-Sphere 核心功能使用 - 图6
    Sharding-JDBC水平分表
    1. 导入pom依赖
    1. <dependency>
    2. <groupId>org.springframework.boot</groupId>
    3. <artifactId>spring-boot-starter</artifactId>
    4. </dependency>
    5. <dependency>
    6. <groupId>mysql</groupId>
    7. <artifactId>mysql-connector-java</artifactId>
    8. <scope>runtime</scope>
    9. </dependency>
    10. <dependency>
    11. <groupId>org.projectlombok</groupId>
    12. <artifactId>lombok</artifactId>
    13. <optional>true</optional>
    14. </dependency>
    15. <dependency>
    16. <groupId>org.springframework.boot</groupId>
    17. <artifactId>spring-boot-starter-test</artifactId>
    18. <scope>test</scope>
    19. <exclusions>
    20. <exclusion>
    21. <groupId>org.junit.vintage</groupId>
    22. <artifactId>junit-vintage-engine</artifactId>
    23. </exclusion>
    24. </exclusions>
    25. </dependency>
    26. <dependency>
    27. <groupId>com.alibaba</groupId>
    28. <artifactId>druid-spring-boot-starter</artifactId>
    29. <version>1.1.20</version>
    30. </dependency>
    31. <dependency>
    32. <groupId>org.apache.shardingsphere</groupId>
    33. <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    34. <version>4.0.0-RC1</version>
    35. </dependency>
    36. <dependency>
    37. <groupId>com.baomidou</groupId>
    38. <artifactId>mybatis-plus-boot-starter</artifactId>
    39. <version>3.0.5</version>
    40. </dependency>
  3. 创建course_db数据库,并创建course_1,course_2两张表,建表SQL如上

  4. 创建实体类,以及Mapper

    1. // 实体类
    2. @Data
    3. public class Course {
    4. private Long cid;
    5. private String cname;
    6. private Long userId;
    7. private String cStatus;
    8. }
    9. //Mapper
    10. @Repository
    11. public interface CourseMapper extends BaseMapper<Course> {
    12. }

    4. 配置SpringBoot

    ```

    shardingjdbc 分片策略

    配置数据源,给数据源起名称

    spring.shardingsphere.datasource.names=m1

    一个实体类对应两张表,覆盖

    spring.main.allow-bean-definition-overriding=true

    配置数据源具体内容,包含连接池,驱动,地址,用户名和密码

    spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource spring.shardingsphere.datasource.m1.driver-class-name=com.mysql.cj.jdbc.Driver spring.shardingsphere.datasource.m1.url=jdbc:mysql://localhost:3306/sharding-sphere?serverTimezone=GMT%2B8 spring.shardingsphere.datasource.m1.username=root spring.shardingsphere.datasource.m1.password=123456

指定 course 表分布情况,配置表在哪个数据库里面,表名称都是什么 m1.course_1 , m1.course_2

spring.shardingsphere.sharding.tables.course.actual-data-nodes=m1.course_$->{1..2}

指定 course 表里面主键 cid

spring.shardingsphere.sharding.tables.course.key-generator.column=cid

生成策略 SNOWFLAKE

spring.shardingsphere.sharding.tables.course.key-generator.type=SNOWFLAKE

指定分片策略 约定 cid 值偶数添加到 course_1 表,如果 cid 是奇数添加到 course_2 表

spring.shardingsphere.sharding.tables.course.table-strategy.inline.sharding-column=cid spring.shardingsphere.sharding.tables.course.table-strategy.inline.algorithm-expression=course_$->{cid%2+1}

打开sql打印功能

spring.shardingsphere.props.sql.show=true

  1. <a name="tMXyQ"></a>
  2. ## 5. 编写测试用例
  3. ```java
  4. @Test
  5. public void addCourse() {
  6. for (int i = 1; i <= 10; i++) {
  7. Course course = new Course();
  8. course.setCname("java" + i);
  9. course.setUserId(100L);
  10. course.setCStatus("Normal" + i);
  11. courseMapper.insert(course);
  12. }
  13. }
  14. @Test
  15. public void findCourse() {
  16. QueryWrapper<Course> wrapper = new QueryWrapper<>();
  17. wrapper.eq("cid", 474163991510253568L);
  18. Course course = courseMapper.selectOne(wrapper);
  19. System.out.println(course);
  20. }
  1. 测试结果
    Sharding-Sphere 核心功能使用 - 图7

    Sharding-Sphere 核心功能使用 - 图8
    Sharding-JDBC实现水平分库
    1. 创建两个数据库,分别为edu_db_1,edu_db_2,分别执行上述的db.sql文件,创建相应的表
    2. 修改配置文件,设置水平分库的策略规则 ```

    水平分库配置文件

    shardingjdbc 分片策略

    配置数据源,给数据源起名称

    水平分库,配置两个datasource

    spring.shardingsphere.datasource.names=m1,m2

    一个实体类对应两张表,覆盖

    spring.main.allow-bean-definition-overriding=true

    配置第一个数据源具体内容,包含连接池,驱动,地址,用户名和密码

    spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource spring.shardingsphere.datasource.m1.driver-class-name=com.mysql.cj.jdbc.Driver spring.shardingsphere.datasource.m1.url=jdbc:mysql://localhost:3306/edu_db_1?serverTimezone=GMT%2B8 spring.shardingsphere.datasource.m1.username=root spring.shardingsphere.datasource.m1.password=123456

    配置第二个数据源具体内容,包含连接池,驱动,地址,用户名和密码

    spring.shardingsphere.datasource.m2.type=com.alibaba.druid.pool.DruidDataSource spring.shardingsphere.datasource.m2.driver-class-name=com.mysql.cj.jdbc.Driver spring.shardingsphere.datasource.m2.url=jdbc:mysql://localhost:3306/edu_db_2?serverTimezone=GMT%2B8 spring.shardingsphere.datasource.m2.username=root spring.shardingsphere.datasource.m2.password=123456

    指定 course 表分布情况,配置表在哪个数据库里面,表名称都是什么 m1.course_1 , m1.course_2

    spring.shardingsphere.sharding.tables.course.actual-data-nodes=m$->{1..2}.course_$->{1..2}

    指定 course 表里面主键 cid

    spring.shardingsphere.sharding.tables.course.key-generator.column=cid

    生成策略 SNOWFLAKE

    spring.shardingsphere.sharding.tables.course.key-generator.type=SNOWFLAKE

    指定表分片策略 约定 cid 值偶数添加到 course_1 表,如果 cid 是奇数添加到 course_2 表

    spring.shardingsphere.sharding.tables.course.table-strategy.inline.sharding-column=cid spring.shardingsphere.sharding.tables.course.table-strategy.inline.algorithm-expression=course_$->{cid%2+1}

指定数据库分片策略 约定 user_id 是偶数添加 m1 ,是 奇数添加 m2

spring.shardingsphere.sharding.tables.course.database-strategy.inline.sharding-column=user_id spring.shardingsphere.sharding.tables.course.database-strategy.inline.algorithm-expression=m$->{user_id % 2 + 1}

打开sql打印功能

spring.shardingsphere.props.sql.show=true

  1. 主要修改内容为:

spring.shardingsphere.datasource.names=m1,m2

添加第二个数据源

spring.shardingsphere.datasource.m2.type=com.alibaba.druid.pool.DruidDataSource spring.shardingsphere.datasource.m2.driver-class-name=com.mysql.cj.jdbc.Driver spring.shardingsphere.datasource.m2.url=jdbc:mysql://localhost:3306/edu_db_2?serverTimezone=GMT%2B8 spring.shardingsphere.datasource.m2.username=root spring.shardingsphere.datasource.m2.password=123456

修改course表的路由规则

spring.shardingsphere.sharding.tables.course.actual-data-nodes=m$->{1..2}.course_$->{1..2}

指定数据库分片策略 约定 user_id 是偶数添加 m1 ,是 奇数添加 m2

spring.shardingsphere.sharding.tables.course.database-strategy.inline.sharding-column=user_id spring.shardingsphere.sharding.tables.course.database-strategy.inline.algorithm-expression=m$->{user_id % 2 + 1}

  1. <a name="qtIUA"></a>
  2. ## 3.编写测试用例测试水平分库情况
  3. ```java
  4. public void addCourseDb() {
  5. for (int i = 0; i < 20; i++) {
  6. Course course = new Course();
  7. course.setCname("javaDemo1");
  8. course.setUserId((long)(i + 1));
  9. course.setCStatus("Normal1");
  10. courseMapper.insert(course);
  11. }
  12. }
  13. @Test
  14. public void findCourseDb() {
  15. QueryWrapper<Course> objectQueryWrapper = new QueryWrapper<>();
  16. objectQueryWrapper.eq("user_id", 111L);
  17. objectQueryWrapper.eq("cid", 474167742677647361L);
  18. Course course = courseMapper.selectOne(objectQueryWrapper);
  19. System.out.println(course);
  20. }


Sharding-JDBC实现垂直分库
1. 创建数据库和表(创建user_db数据库和t_user表)
2. 修改配置文件,设置水平分库的策略规则

  1. # 垂直分库配置文件
  2. # shardingjdbc 分片策略
  3. # 配置数据源,给数据源起名称
  4. # 水平分库,配置两个datasource
  5. spring.shardingsphere.datasource.names=m1,m2,m0
  6. # 一个实体类对应两张表,覆盖
  7. spring.main.allow-bean-definition-overriding=true
  8. # 配置第一个数据源具体内容,包含连接池,驱动,地址,用户名和密码
  9. spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource
  10. spring.shardingsphere.datasource.m1.driver-class-name=com.mysql.cj.jdbc.Driver
  11. spring.shardingsphere.datasource.m1.url=jdbc:mysql://localhost:3306/edu_db_1?serverTimezone=GMT%2B8
  12. spring.shardingsphere.datasource.m1.username=root
  13. spring.shardingsphere.datasource.m1.password=123456
  14. # 配置第二个数据源具体内容,包含连接池,驱动,地址,用户名和密码
  15. spring.shardingsphere.datasource.m2.type=com.alibaba.druid.pool.DruidDataSource
  16. spring.shardingsphere.datasource.m2.driver-class-name=com.mysql.cj.jdbc.Driver
  17. spring.shardingsphere.datasource.m2.url=jdbc:mysql://localhost:3306/edu_db_2?serverTimezone=GMT%2B8
  18. spring.shardingsphere.datasource.m2.username=root
  19. spring.shardingsphere.datasource.m2.password=123456
  20. # 配置第三个数据源具体内容,包含连接池,驱动,地址,用户名和密码
  21. spring.shardingsphere.datasource.m0.type=com.alibaba.druid.pool.DruidDataSource
  22. spring.shardingsphere.datasource.m0.driver-class-name=com.mysql.cj.jdbc.Driver
  23. spring.shardingsphere.datasource.m0.url=jdbc:mysql://localhost:3306/user_db?serverTimezone=GMT%2B8
  24. spring.shardingsphere.datasource.m0.username=root
  25. spring.shardingsphere.datasource.m0.password=123456
  26. # 配置 user_db 数据库里面 t_user 专库专表
  27. spring.shardingsphere.sharding.tables.t_user.actual-data-nodes=m$->{0}.t_user
  28. # 指定user表的主键user_id
  29. spring.shardingsphere.sharding.tables.t_user.key-generator.column=user_id
  30. spring.shardingsphere.sharding.tables.t_user.key-generator.type=SNOWFLAKE
  31. # 指定user表的分库分表策略
  32. spring.shardingsphere.sharding.tables.t_user.table-strategy.inline.sharding-column=user_id
  33. spring.shardingsphere.sharding.tables.t_user.table-strategy.inline.algorithm-expression=t_user
  34. # 指定 course 表分布情况,配置表在哪个数据库里面,表名称都是什么 m1.course_1 , m1.course_2
  35. spring.shardingsphere.sharding.tables.course.actual-data-nodes=m$->{1..2}.course_$->{1..2}
  36. # 指定 course 表里面主键 cid
  37. spring.shardingsphere.sharding.tables.course.key-generator.column=cid
  38. # 生成策略 SNOWFLAKE
  39. spring.shardingsphere.sharding.tables.course.key-generator.type=SNOWFLAKE
  40. # 指定表分片策略 约定 cid 值偶数添加到 course_1 表,如果 cid 是奇数添加到 course_2 表
  41. spring.shardingsphere.sharding.tables.course.table-strategy.inline.sharding-column=cid
  42. spring.shardingsphere.sharding.tables.course.table-strategy.inline.algorithm-expression=course_$->{cid%2+1}
  43. # 指定数据库分片策略 约定 user_id 是偶数添加 m1 ,是 奇数添加 m2
  44. spring.shardingsphere.sharding.tables.course.database-strategy.inline.sharding-column=user_id
  45. spring.shardingsphere.sharding.tables.course.database-strategy.inline.algorithm-expression=m$->{user_id % 2 + 1}
  46. #打开sql打印功能
  47. spring.shardingsphere.props.sql.show=true

主要修改如下的配置

  1. spring.shardingsphere.datasource.names=m1,m2,m0
  2. # 配置第三个数据源具体内容,包含连接池,驱动,地址,用户名和密码
  3. spring.shardingsphere.datasource.m0.type=com.alibaba.druid.pool.DruidDataSource
  4. spring.shardingsphere.datasource.m0.driver-class-name=com.mysql.cj.jdbc.Driver
  5. spring.shardingsphere.datasource.m0.url=jdbc:mysql://localhost:3306/user_db?serverTimezone=GMT%2B8
  6. spring.shardingsphere.datasource.m0.username=root
  7. spring.shardingsphere.datasource.m0.password=123456
  8. # 配置 user_db 数据库里面 t_user 专库专表
  9. spring.shardingsphere.sharding.tables.t_user.actual-data-nodes=m$->{0}.t_user
  10. # 指定user表的主键user_id
  11. spring.shardingsphere.sharding.tables.t_user.key-generator.column=user_id
  12. spring.shardingsphere.sharding.tables.t_user.key-generator.type=SNOWFLAKE
  13. # 指定user表的分库分表策略
  14. spring.shardingsphere.sharding.tables.t_user.table-strategy.inline.sharding-column=user_id
  15. spring.shardingsphere.sharding.tables.t_user.table-strategy.inline.algorithm-expression=t_user
  1. 测试用例
    1. @Test
    2. public void addUserDb(){
    3. User user = new User();
    4. user.setUsername("lucy");
    5. user.setUstatus("a");
    6. userMapper.insert(user);
    7. }

    Sharding-JDBC操作公共表

  2. 何为公共表
    l 存储固定数据的表,数据很少发生变化,查询时候经常进行关联
    l 在每个数据库中创建出相同结构的表
    2. 在每个库中添加相同的表结构
    Sharding-Sphere 核心功能使用 - 图9

    Sharding-Sphere 核心功能使用 - 图10
    3. 添加配置文件信息
    1. # 配置公共表的信息
    2. spring.shardingsphere.sharding.broadcast-tables=t_udict
    3. spring.shardingsphere.sharding.tables.t_udict.key-generator.column=dict_id
    4. spring.shardingsphere.sharding.tables.t_udict.key-generator.type=SNOWFLAKE
  3. 编写测试代码 ```java // 实体类 @Data @TableName(value = “t_udict”) public class Udict { private Long dictId; private String ustatus; private String uvalue; } // Mapper @Repository public interface UdictMapper extends BaseMapper {

}

测试crud

// insert @Test public void addDict() { Udict udict = new Udict(); udict.setUstatus(“a”); udict.setUvalue(“已启用”); udictMapper.insert(udict); } // delete @Test public void deleteDict() { QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq(“dict_id”, 474180202679762945L); udictMapper.delete(wrapper); } //select @Test public void selectDict() { QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq(“dict_id”, 474180202679762945L); udictMapper.selectOne(wrapper); } // update @Test public void updateDict() { QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq(“dict_id”, 474180852427784193L); Udict udict = udictMapper.selectOne(wrapper); udict.setUvalue(“update”); udictMapper.update(udict, wrapper); }

  1. <a name="YqMze"></a>
  2. ## Shareding-JDBC实现读写分离
  3. 1. 读写分离的概念<br />为了保证数据库的稳定性,数据库基本都采用双机热备的功能,也就是,一台数据库服务器,对外提供增删改的业务功能,另一台数据库服务器,对外提供读操作的业务功能。<br />原理,让主库Master处理事务性强(增,删,改)操作,让从库(slave)处理Select(查)的操作<br />读写分离的原理<br />主从复制:当主库有写入的操作(insert/update/delete),将会写入binlog,从库通过binlog获取主库的操作,进行同步<br />读写分离:insert/update/delete主库,select从库<br />![](https://cdn.nlark.com/yuque/0/2020/jpeg/1538293/1599785295239-5a81cd9a-eb39-4287-9817-830d7a3109ea.jpeg#align=left&display=inline&height=297&margin=%5Bobject%20Object%5D&originHeight=339&originWidth=506&status=done&style=none&width=444)<br />Sharding-JDBC通过SQL语句的语义解析,实现读写分离的过程,不会进行数据的同步。<br />2.MySQL配置读写分离<br />详见:[MySQL 主从复制搭建](https://www.yuque.com/zhanyifan-rkxpe/grf7g5/hzu3ne)<br />3.配置读写分离策略

配置主从复制

添加s0 datasource

spring.shardingsphere.datasource.names=m1,m2,m0,s0

user_db的从服务器

spring.shardingsphere.datasource.s0.type=com.alibaba.druid.pool.DruidDataSource spring.shardingsphere.datasource.s0.driver-class-name=com.mysql.cj.jdbc.Driver spring.shardingsphere.datasource.s0.url=jdbc:mysql://192.168.137.131:3306/user_db?serverTimezone=GMT%2B8 spring.shardingsphere.datasource.s0.username=root spring.shardingsphere.datasource.s0.password=123456 spring.shardingsphere.sharding.master-slave-rules.ds0.master-data-source-name=m0 spring.shardingsphere.sharding.master-slave-rules.ds0.slave-data-source-names=s0 spring.shardingsphere.sharding.tables.t_user.actual-data-nodes=ds0.t_user

  1. 4. 编写测试用例测试读写分离
  2. ```java
  3. @Test
  4. public void addUser() {
  5. User user = new User();
  6. user.setUsername("read write");
  7. user.setUstatus("a");
  8. userMapper.insert(user);
  9. }
  10. @Test
  11. public void findUser() {
  12. QueryWrapper<User> wrapper = new QueryWrapper<>();
  13. // 设置 userid 值
  14. wrapper.eq("user_id",465508031619137537L);
  15. User user = userMapper.selectOne(wrapper);
  16. System.out.println(user);
  17. }
  1. 测试结果
    添加:往m0库中进行添加
    Sharding-Sphere 核心功能使用 - 图11
    查询:往s0库中进行查询,从而达到一个读写分离的效果。
    Sharding-Sphere 核心功能使用 - 图12
    最终结果,符合上述配置文件中描述的,写请求往m0,读请求往s0.