# Sharding-JDBC

Sharding-JDBC 是当当网研发的开源分布式数据库中间件,从3.0开始Sharding-JDBC被包含在Sharding-Sphere中,之后该项目进入进入Apache孵化器,4.0版本之后的版本为Apache版本。

Sharding-JDBC的核心功能为数据分片和读写分离,通过 Sharding-JDBC ,应用可以透明的使用 JDBC 访问已经分库分表、读写分离的多个数据源而不用送心数据源的数量以及数据如何分布。

  • 适用于任何基于 Java 的 ORM 框架,如:Hibernate,Mybatis,Spring JDBC Template或直接使用 JDBC。
  • 基于任何第三方的数据库连接池,如:DBCP,C3PO,BoneCP,Druid,HikariCP 等。
  • 支持任意实现DBC规范的数据库。目前支持MySQL,Oracle,SQLServer和 PostgreSQL。

# 项目

  • ShardingSphere-JDBC 轻量级Java框架
  • ShardingSphere-Proxy 数据库代理
  • ShardingSphere-Sidecar(规划中) Kubernetes的云原生数据库代理

# 分表方式

  1. 垂直分表
  2. 垂直分库
  3. 水平分表
  4. 水平分库

# 垂直分表

将一个表常用的字段和不常用的进行拆分(将常用的字段放到一个表,不常用的放到另一个表中),就是垂直分表
垂直分表

# 垂直分库

垂直分库是指按照业务将表进行分类,分布到不同的数据库上面,每个库可以放在不同的服务器上,它的核心理念是专库专用。
垂直分库

# 水平分库

水平分库是把同一个表的数据按一定规则拆到不同的数据库中,每个库可以放在不同的服务器上。
水平分库

对比

垂直分库是把不同表拆到不同数据库中,它是对数据行的拆分,不影响表结构

# 水平分表

水平分表是在同一个数据库内,把同一个表的数据按一定规则拆到多个表中,将分库的多个表,按照一定规则插入,如id值为基数则插入1表,偶数插入2表

# 安装

# maven

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.28</version>
</dependency>

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.0.0</version>
</dependency>

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.16</version>
</dependency>


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


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

# 简单运行

# properties

mybatis.configuration.map-underscore-to-camel-case=true
spring.main.allow-bean-definition-overriding=true

logging.level.org.springframework.web=info
logging.level.com.g.shardingjdbc=debug
logging.level.druid.sql=debug
logging.level.org.springframework.boot=debug


#sharding-jdbc 配置
#数据源名称
spring.shardingsphere.datasource.names=m1
#连接池(上面名称叫啥这里就要写啥 m1 就写m1)
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/order_db?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true&rewriteBatchedStatements=true
spring.shardingsphere.datasource.m1.username=root
spring.shardingsphere.datasource.m1.password=root

#数据分布情况,数据节点
#t_order可以任意,但是在SQL插入的时候就要跟这里对应
spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=m1.t_order_$->{1..2}

#指定t_order表的主键生成策略为SNOWFLAKE
spring.shardingsphere.sharding.tables.t_order.key-generator.column=order_id
spring.shardingsphere.sharding.tables.t_order.key-generator.type=SNOWFLAKE

# 指定t_order表的分片策略,分片策略包括分片和分片算法
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.sharding-column=order_id
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.algorithm-expression=t_order_$->{order_id % 2 + 1}

# yaml

spring:
  main:
    allow-bean-definition-overriding: true
  shardingsphere:
    datasource:
      names: m1
      m1:
        type: com.alibaba.druid.pool.DruidDataSource
        driverClassName: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/order_db?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true&rewriteBatchedStatements=true
        username: root
        password: root
    sharding:
      tables:
        t_order:
          actual-data-nodes: m1.t_order_$->{1..2}
          key-generator:
            column: order_id
            type: SNOWFLAKE
          table-strategy:
            inline:
              sharding-column: order_id
              algorithm-expression: t_order_$->{order_id % 2 + 1}
mybatis:
  configuration:
    map-underscore-to-camel-case: true
  mapper-locations: mapper/*.xml

#

DROP TABLE IF EXISTS `t_order_1`;
CREATE TABLE `t_order_1`  (
  `order_id` bigint NOT NULL COMMENT '订单id',
  `price` decimal(10, 2) NOT NULL COMMENT '订单价格',
  `user_id` bigint NOT NULL COMMENT '下单用户id',
  `status` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '订单状态',
  PRIMARY KEY (`order_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;

# 执行sql

@Repository
@Mapper
public interface TOrderMapper {

    @Insert("insert into t_order(price,user_id,status) values(1,1,1)")
    int insert();
}

# 总结

最终这个数据会进入t_order_2中,因为他取模+1后的数值是偶数