ShardingSphere-JDBC5.1.1实现数据库分片最完整讲解

前言

使用ShardingSphere分库分表之前,先介绍一下定义及流程,这样咱们下边的每一个配置都可以做到心里有数,另外在配置过程中会出现很多意外报错,配置中都会提到的。
概念、流程都明白的可以直接跳到最后看完整配置。
首先说一下分片的类型,可以分为:分库、分表、分库分表

  • 分库
    根据官方定义理解如下,可以看到下边截图,有两个库,每个库里有相同的3个表
    在这里插入图片描述
  • 分表
    针对表进行分片,可以是单表,可以是关联表(比如order和order_item)
    在这里插入图片描述
  • 分库分表
    将整表水平切分成多个分表,然后将这些分表分布到不同的库中。
    在这里插入图片描述
    当然,数据节点的分布方式又可以分成两种方式:均匀分布的数据节点、自定义的数据节点
    均匀分布的数据节点
    在这里插入图片描述
    自定义的数据节点
    在这里插入图片描述

演示案例

shardingsphere版本依赖信息

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

其他主要依赖信息

	<dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>1.1.22</version>
    </dependency>
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.4.1</version>
    </dependency>
	<dependency>
	  <groupId>mysql</groupId>
	  <artifactId>mysql-connector-java</artifactId>
	  <version>8.0.21</version>
	</dependency>
	<dependency>
	  <groupId>org.apache.shiro</groupId>
	  <artifactId>shiro-spring-boot-starter</artifactId>
	  <version>1.7.1</version>
	</dependency>
 	<dependency>
	  <groupId>org.crazycake</groupId>
	  <artifactId>shiro-redis</artifactId>
	  <version>3.1.0</version>
	  <exclusions>
	      <exclusion>
	          <groupId>org.apache.shiro</groupId>
	          <artifactId>shiro-core</artifactId>
	      </exclusion>
	      <exclusion>
	          <groupId>com.puppycrawl.tools</groupId>
	          <artifactId>checkstyle</artifactId>
	      </exclusion>
	  </exclusions>
 	</dependency>
	 <!-- Redis -->
	 <dependency>
	     <groupId>org.springframework.boot</groupId>
	     <artifactId>spring-boot-starter-data-redis</artifactId>
	 </dependency>
	 <!--JWT-->
	 <dependency>
	     <groupId>com.auth0</groupId>
	     <artifactId>java-jwt</artifactId>
	     <version>3.11.0</version>
	 </dependency>
单库分表演示
  • 准备数据库表
    在这里插入图片描述

  • 实体类
    在这里插入图片描述

  • 配置讲解

rules:
  # 步骤:设置分片节点(一个整表分为了多少个分表)->分片规则(根据主键的分片算法,这样才能知道数据存取位置)->主键生成规则(uuid或者雪花算法SNOWFLAKE,可以不配置,不配置也可以)
   sharding:
     tables:
       # 配置cl_user的分表的规则
       cl_user:
         # 拥有几个分片表0-3,表达式参考 h ttps://shardingsphere.apache.org/document/current/cn/features/sharding/concept/inline-expression/
         actual-data-nodes: demo.cl_user_$->{0..3}
         table-strategy:
           standard:
             sharding-column: id
             sharding-algorithm-name: table-inline
     # 配置分片算法
     sharding-algorithms:
       table-inline:
         # 算法类型 参考 https://shardingsphere.apache.org/document/current/cn/user-manual/shardingsphere-jdbc/builtin-algorithm/sharding/
         type: INLINE
         props:
           algorithm-expression: cl_user_$->{id % 4}

这里会出现三个常见问题

  • 分片算法跟主键不对应得问题(Inline sharding algorithms expression xxx and sharding column xx not mat)
    原因是因为采用INLINE算法,然后你的注解可能是字符串类型,将类型改成Long或者Integer即可。

  • 插入语句不支持分片表路由到多个数据节点(Insert statement does not support sharding table routing to multiple data nodes)
    原因是实体类中,主键没有标识出来,加上标识注解即可,比如mybatis就用@TableId注解即可。
    在这里插入图片描述

  • sharding-algorithms配置项不加载问题【最难定位的错误】
    这个问题可能会报Route table null does not exist【INLINE算法】或者by zero【HASH_MOD算法】,原因就是配置没加载,因为项目中用了shiro,shiro中注入了userservice,ShardingSphere有引来了shiro得filter,所以会引发循环依赖,使用@lazy注解在你的service注入上。
    在这里插入图片描述
    这里,因为我的分片主键id是string,所以需要换成其他算法,选了(哈希取模分片算法)HASH_MOD,原因一是会报算法和主键不匹配的错,另一个原因是发现用(INLINE+cl_user_$->{id % 4}),每次添加新数据时,因为id生成的是19位的Long数据,取模之后大部分得到的结果都是1,2号表插入,反正我插入了几十条,算出来的都是1,2号表,0和3基本一条都没插入,为了平均和简单,所以直接选了HASH_MOD,测试还算是比较平均的插入到每张表了。

# 配置分片算法
  sharding-algorithms:
    table-inline:
      # 算法类型 参考 https://shardingsphere.apache.org/document/current/cn/user-manual/shardingsphere-jdbc/builtin-algorithm/sharding/
      type: HASH_MOD
      props:
        sharding-count: 4 # 分片数量,自定义根据实际的分片
  • 完整代码
common: &common
  type: com.alibaba.druid.pool.DruidDataSource
  driver-class-name: com.mysql.cj.jdbc.Driver
  initial-size: 5
  min-idle: 5
  maxActive: 20
  # 配置获取连接等待超时的时间
  maxWait: 60000
  # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
  timeBetweenEvictionRunsMillis: 60000
  # 配置一个连接在池中最小生存的时间,单位是毫秒
  minEvictableIdleTimeMillis: 300000
  #Oracle需要打开注释
  #validationQuery: SELECT 1 FROM DUAL
  testWhileIdle: true
  testOnBorrow: false
  testOnReturn: false
  # 打开PSCache,并且指定每个连接上PSCache的大小
  poolPreparedStatements: true
  maxPoolPreparedStatementPerConnectionSize: 20
  # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
  filters: stat,wall,slf4j
  # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
  connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
  wall:
    multi-statement-allow: true
spring:
  autoconfigure:
    exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
  datasource:
    druid:
      stat-view-servlet:
        enabled: true
        loginUsername: admin
        loginPassword: 123456
        allow:
      web-stat-filter:
        enabled: true
  shardingsphere:
    props:
      # 是否在日志中打印 SQL 更多属性参考->https://shardingsphere.apache.org/document/current/cn/user-manual/shardingsphere-jdbc/props/
      sql-show: true
    datasource:
      names: slave1
      slave1:
        url: jdbc:mysql://192.168.150.129:3306/test_data?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&allowMultiQueries=true&serverTimezone=Asia/Shanghai
        username: root
        password: root
        <<: *common
    rules:
      # 步骤:设置分片节点(一个整表分为了多少个分表)->分片规则(根据主键的分片算法,这样才能知道数据存取位置)->主键生成规则(uuid或者雪花算法SNOWFLAKE)
      sharding:
        tables:
          # 配置cl_user的分表的规则
          cl_user:
            # 拥有几个分片表0-3,表达式参考 https://shardingsphere.apache.org/document/current/cn/features/sharding/concept/inline-expression/
            actual-data-nodes: slave1.cl_user_$->{0..3}
            table-strategy:
              standard:
                sharding-column: id
                sharding-algorithm-name: table-inline
#              key-generate-strategy:
#                column: id
#                key-generator-name: snowflake

        # 配置分片算法
        sharding-algorithms:
          table-inline:
            # 算法类型 参考 https://shardingsphere.apache.org/document/current/cn/user-manual/shardingsphere-jdbc/builtin-algorithm/sharding/
            type: HASH_MOD
            props:
              sharding-count: 4
#        key-generators:
#          snowflake:
#            type: SNOWFLAKE
  redis:
    open: false  # 是否开启redis缓存  true开启   false关闭
    database: 1
    host: 127.0.0.1
    port: 6379
    password:    # 密码(默认为空)
    timeout: 6000ms  # 连接超时时长(毫秒)
    jedis:
      pool:
        max-active: 1000  # 连接池最大连接数(使用负值表示没有限制)
        max-wait: -1ms      # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-idle: 10      # 连接池中的最大空闲连接
        min-idle: 5       # 连接池中的最小空闲连接

分布式主键算法策略注释了,因为我发现这个版本配置和不配置效果一样。

分库

只改yml配置文件即可,增加slave0库
在这里插入图片描述

datasource:
      names: slave1,slave0
      slave1:
        url: jdbc:mysql://192.168.150.129:3306/test_data?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&allowMultiQueries=true&serverTimezone=Asia/Shanghai
        username: root
        password: root
        <<: *common
      slave0:
        url: jdbc:mysql://192.168.150.132:3306/test_data?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&allowMultiQueries=true&serverTimezone=Asia/Shanghai
        username: root
        password: root
        <<: *common
    rules:
      # 步骤:设置分片节点(一个整表分为了多少个分表)->分片规则(根据主键的分片算法,这样才能知道数据存取位置)->主键生成规则(uuid或者雪花算法SNOWFLAKE)
      sharding:
        tables:
          # 配置cl_user的分表的规则
          cl_user:
            # 拥有几个分片表0-3,表达式参考 https://shardingsphere.apache.org/document/current/cn/features/sharding/concept/inline-expression/
            actual-data-nodes: slave$->{0..1}.cl_user_$->{0..3}
            table-strategy:
              standard:
                sharding-column: id
                sharding-algorithm-name: table-inline
# 和下边的默认分库配置(default-database-strategy)任选一个即可
#            database-strategy:
#              standard:
#                sharding-column: id
#                sharding-algorithm-name: database-inline
        # 配置分片算法
        sharding-algorithms:
          # 分表算法
          table-inline:
            # 算法类型 参考 https://shardingsphere.apache.org/document/current/cn/user-manual/shardingsphere-jdbc/builtin-algorithm/sharding/
            type: HASH_MOD
            props:
              sharding-count: 4
          # 分库算法
          database-inline:
            type: HASH_MOD
            props:
              sharding-count: 2
        default-database-strategy:
          standard:
            sharding-column: id
            sharding-algorithm-name: database-inline

这里增加了两个配置一个分库算法database-inline,一个分库算法引用配置default-database-strategy,另外,提醒一下大家,分库命名最好都从0开始,比如,最开始我用的是slave1,slave2,结果就会一直报数据库路由找不到的错误,原因就是取模算法中会取到0,所以找0号库找不到。

分库分表

在这里插入图片描述
因为表分布在不同的库中,所以对比算法要求就高了,单纯的内置算法就不足以满足需求,所以需要自定义算法,这里我将上边的slave0和slave1互换了名字,正好对应分表0,1和2,3,方便理解,另外,提一下,行表达式可以写三元表达式,比如:
在这里插入图片描述
好了,话不多说,正式开始

rules:
	 # 步骤:设置分片节点(一个整表分为了多少个分表)->分片规则(根据主键的分片算法,这样才能知道数据存取位置)->主键生成规则(uuid或者雪花算法SNOWFLAKE)
	  sharding:
	    tables:
	      # 配置cl_user的分表的规则
	      cl_user:
	        # 拥有几个分片表0-3,表达式参考 https://shardingsphere.apache.org/document/current/cn/features/sharding/concept/inline-expression/
	        actual-data-nodes: slave0.cl_user_$->{0..1},slave1.cl_user_$->{2..3}
	        table-strategy:
	          standard:
	            sharding-column: id
	            sharding-algorithm-name: table-myself
	    # 配置分片算法
	    sharding-algorithms:
	      # 分表算法
	      table-myself:
	        type: MYSELF
	        props:
	          #数据库和表的对应关系,自定义
	          databases-tables-relevance: "{0:[0,1],1:[2,3]}"
	      # 分库算法
	      database-inline:
	        type: INLINE
	        props:
	          algorithm-expression: slave$->{id % 2}
	    default-database-strategy:
	      standard:
	        sharding-column: id
	        sharding-algorithm-name: database-inline

这里我用了自定义方法table-myself.
规则详情:根据分库算法算出来0号库还是1号库,然后再根据库来随机选出来库所对应的表。
在这里插入图片描述
当然,这些算法是根据你自己的需求自己写的,我这里举个例子,详细配置自定义分片规则,请跳这里
自定义分片算法
好啦,读写分离+分库分表,读写分离,自定义算法等等,可以去我的个人主页一一查看。

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值