分库分表-ShardingSphere-ShardingJDBC

分片和分区的区别

Sharding 分片Partition分区
存储依赖可跨越DB 可跨越物理机器可跨越表空间,不能跨DB存储
数据划分常见为时间、范围、面向服务等范围、Hash、列表、混合分区等
存储方式分布式集中式
扩展性Scale Out (水平扩展)Scale Up(垂直扩展)
可用性无单点存在单点(DB本身)
价格低廉适中(DAS)甚至昂贵(SAN)
应用场景Web 2.0网站多数传统应用

ShardingSphere

version:4.x

Apache ShardingSphere 是一套开源的分布式数据库中间件解决方案组成的生态圈,它由 JDBC、Proxy 和 Sidecar(规划中)这 3 款相互独立,却又能够混合部署配合使用的产品组成。 它们均提供标准化的数据分片、分布式事务和数据库治理功能,可适用于如 Java 同构、异构语言、云原生等各种多样化的应用场景。

Sharding-JDBC

依赖

<dependency>
	<groupId>org.apache.shardingsphere</groupId>
	<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
	<version>4.0.0</version>
</dependency>

库:test1 schema

-- ----------------------------
-- Table structure for user_1
-- ----------------------------
DROP TABLE IF EXISTS `user_1`;
CREATE TABLE `user_1`  (
  `id` bigint(20) NOT NULL,
  `uuid` bigint(20) NULL DEFAULT NULL,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Table structure for user_2
-- ----------------------------
DROP TABLE IF EXISTS `user_2`;
CREATE TABLE `user_2`  (
  `id` bigint(20) NOT NULL,
  `uuid` bigint(20) NULL DEFAULT NULL,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;

库:test2 schema

-- ----------------------------
-- Table structure for user_1
-- ----------------------------
DROP TABLE IF EXISTS `user_1`;
CREATE TABLE `user_1`  (
  `id` bigint(20) NOT NULL,
  `uuid` bigint(20) NULL DEFAULT NULL,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Table structure for user_2
-- ----------------------------
DROP TABLE IF EXISTS `user_2`;
CREATE TABLE `user_2`  (
  `id` bigint(20) NOT NULL,
  `uuid` bigint(20) NULL DEFAULT NULL,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;

SET FOREIGN_KEY_CHECKS = 1;

配置文件

spring:
  shardingsphere:
    #数据源
    datasource:
      names: test1,test2
      test1:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3306/test_1
        username: root
        password: abc123
      test2:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3306/test_2
        username: root
        password: abc123
    #分片
    sharding:
      tables:
        user:
          #由数据源名 + 表名组成,以小数点分隔。多个表以逗号分隔,支持inline表达式。
          #缺省表示使用已知数据源与逻辑表名称生成数据节点,用于广播表(即每个库中都需要一个同样的表用于关联查询,多为字典表)或只分库不分表且所有库的表结构完全一致的情况
          actual-data-nodes: test$->{1..2}.user_$->{1..2}
          key-generator:
            #自增列名称,缺省表示不使用自增主键生成器
            column: id
            #自增列值生成器类型,缺省表示使用默认自增列值生成器。可使用用户自定义的列值生成器或选择内置类型:SNOWFLAKE/UUID
            type: SNOWFLAKE
          table-strategy:
            inline:
              #分表列名称
              sharding-column: id
              #分表算法行表达式,需符合groovy语法
              #偶数进表1,奇数进表2
              algorithm-expression: user_$->{id%2+1}
          database-strategy:
            inline:
              #分片列名称
              sharding-column: uuid
              #分片算法行表达式,需符合groovy语法
              #偶数进库1,奇数进库2
              algorithm-expression: test$->{uuid%2+1}
    props:
      sql:
        show: true

模型

@Data
public class User {

    private Long id;

    private Long uuid;

    private String name;
}

测试

插入10个用户数据

@Test
void add() {
    for (int i = 0; i < 10; i++) {
        User user=new User();
        user.setUuid(111111111111112L);
        user.setName(i+"号用户");
        userDao.insert(user);
    }
}

部分日志验证配置逻辑:

id=1277564054063390721(奇数)
uuid=0(偶数)
用户数据插入到了test1库的user_2表

2020-06-29 19:26:21.799  INFO 18452 --- [           main] ShardingSphere-SQL                       : Rule Type: sharding
2020-06-29 19:26:21.799  INFO 18452 --- [           main] ShardingSphere-SQL                       : Logic SQL: INSERT INTO user  ( id,
uuid,
name )  VALUES  ( ?,
?,
? )
2020-06-29 19:26:21.799  INFO 18452 --- [           main] ShardingSphere-SQL                       : SQLStatement: InsertSQLStatementContext(super=CommonSQLStatementContext(sqlStatement=org.apache.shardingsphere.sql.parser.sql.statement.dml.InsertStatement@5fd18419, tablesContext=TablesContext(tables=[Table(name=user, alias=Optional.absent())], schema=Optional.absent())), columnNames=[id, uuid, name], insertValueContexts=[InsertValueContext(parametersCount=3, valueExpressions=[ParameterMarkerExpressionSegment(startIndex=48, stopIndex=48, parameterMarkerIndex=0), ParameterMarkerExpressionSegment(startIndex=51, stopIndex=51, parameterMarkerIndex=1), ParameterMarkerExpressionSegment(startIndex=54, stopIndex=54, parameterMarkerIndex=2)], parameters=[1277564054063390721, 0, 0号用户])])
2020-06-29 19:26:21.800  INFO 18452 --- [           main] ShardingSphere-SQL                       : Actual SQL: test1 ::: INSERT INTO user_2  ( id,
uuid,
name )  VALUES  (?, ?, ?) ::: [1277564054063390721, 0, 0号用户]

id=1277564056995209217(奇数)
uuid=1(奇数)
用户数据插入到了test2库的user_2表

2020-06-29 19:26:21.838  INFO 18452 --- [           main] ShardingSphere-SQL                       : Rule Type: sharding
2020-06-29 19:26:21.838  INFO 18452 --- [           main] ShardingSphere-SQL                       : Logic SQL: INSERT INTO user  ( id,
uuid,
name )  VALUES  ( ?,
?,
? )
2020-06-29 19:26:21.839  INFO 18452 --- [           main] ShardingSphere-SQL                       : SQLStatement: InsertSQLStatementContext(super=CommonSQLStatementContext(sqlStatement=org.apache.shardingsphere.sql.parser.sql.statement.dml.InsertStatement@5fd18419, tablesContext=TablesContext(tables=[Table(name=user, alias=Optional.absent())], schema=Optional.absent())), columnNames=[id, uuid, name], insertValueContexts=[InsertValueContext(parametersCount=3, valueExpressions=[ParameterMarkerExpressionSegment(startIndex=48, stopIndex=48, parameterMarkerIndex=0), ParameterMarkerExpressionSegment(startIndex=51, stopIndex=51, parameterMarkerIndex=1), ParameterMarkerExpressionSegment(startIndex=54, stopIndex=54, parameterMarkerIndex=2)], parameters=[1277564056995209217, 1, 1号用户])])
2020-06-29 19:26:21.839  INFO 18452 --- [           main] ShardingSphere-SQL                       : Actual SQL: test2 ::: INSERT INTO user_2  ( id,
uuid,
name )  VALUES  (?, ?, ?) ::: [1277564056995209217, 1, 1号用户]

id=1277564057037152258(偶数)
uuid=3(奇数)
用户数据插入到了test2库的user_1表

2020-06-29 19:26:21.848  INFO 18452 --- [           main] ShardingSphere-SQL                       : Rule Type: sharding
2020-06-29 19:26:21.848  INFO 18452 --- [           main] ShardingSphere-SQL                       : Logic SQL: INSERT INTO user  ( id,
uuid,
name )  VALUES  ( ?,
?,
? )
2020-06-29 19:26:21.848  INFO 18452 --- [           main] ShardingSphere-SQL                       : SQLStatement: InsertSQLStatementContext(super=CommonSQLStatementContext(sqlStatement=org.apache.shardingsphere.sql.parser.sql.statement.dml.InsertStatement@5fd18419, tablesContext=TablesContext(tables=[Table(name=user, alias=Optional.absent())], schema=Optional.absent())), columnNames=[id, uuid, name], insertValueContexts=[InsertValueContext(parametersCount=3, valueExpressions=[ParameterMarkerExpressionSegment(startIndex=48, stopIndex=48, parameterMarkerIndex=0), ParameterMarkerExpressionSegment(startIndex=51, stopIndex=51, parameterMarkerIndex=1), ParameterMarkerExpressionSegment(startIndex=54, stopIndex=54, parameterMarkerIndex=2)], parameters=[1277564057037152258, 3, 3号用户])])
2020-06-29 19:26:21.848  INFO 18452 --- [           main] ShardingSphere-SQL                       : Actual SQL: test2 ::: INSERT INTO user_1  ( id,
uuid,
name )  VALUES  (?, ?, ?) ::: [1277564057037152258, 3, 3号用户]

查询

@Test
void get() {
    QueryWrapper<User> userQueryWrapper=new QueryWrapper<>();
    userQueryWrapper.eq("id",1277564057016180737L);
    User user = userDao.selectOne(userQueryWrapper);
    System.out.println(user);
}

由于id=1277564057016180737(奇数)可能在tes1,也可能在test2,但是肯定在表user_2,所以

2020-06-29 19:34:52.485  INFO 20160 --- [           main] ShardingSphere-SQL                       : Rule Type: sharding
2020-06-29 19:34:52.485  INFO 20160 --- [           main] ShardingSphere-SQL                       : Logic SQL: SELECT  id,uuid,name  FROM user 
 
 WHERE (id = ?)
2020-06-29 19:34:52.485  INFO 20160 --- [           main] ShardingSphere-SQL                       : SQLStatement: SelectSQLStatementContext(super=CommonSQLStatementContext(sqlStatement=org.apache.shardingsphere.sql.parser.sql.statement.dml.SelectStatement@7f012923, tablesContext=TablesContext(tables=[Table(name=user, alias=Optional.absent())], schema=Optional.absent())), projectionsContext=ProjectionsContext(startIndex=8, stopIndex=19, distinctRow=false, projections=[ColumnProjection(owner=null, name=id, alias=Optional.absent()), ColumnProjection(owner=null, name=uuid, alias=Optional.absent()), ColumnProjection(owner=null, name=name, alias=Optional.absent())], columnLabels=[id, uuid, name]), groupByContext=org.apache.shardingsphere.sql.parser.relation.segment.select.groupby.GroupByContext@601f264d, orderByContext=org.apache.shardingsphere.sql.parser.relation.segment.select.orderby.OrderByContext@4403bff8, paginationContext=org.apache.shardingsphere.sql.parser.relation.segment.select.pagination.PaginationContext@261275ae, containsSubquery=false)
2020-06-29 19:34:52.486  INFO 20160 --- [           main] ShardingSphere-SQL                       : Actual SQL: test1 ::: SELECT  id,uuid,name  FROM user_2 
 
 WHERE (id = ?) ::: [1277564057016180737]
2020-06-29 19:34:52.486  INFO 20160 --- [           main] ShardingSphere-SQL                       : Actual SQL: test2 ::: SELECT  id,uuid,name  FROM user_2 
 
 WHERE (id = ?) ::: [1277564057016180737]
User(id=1277564057016180737, uuid=2, name=2号用户)

总结

  1. 分片是一个很笼统的概念,具体到可以通过分库和分表来实现
  2. 分库分表主要是按照一定转发规则将数据进行合理分配存储

个人公众号

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值