ShardingSphere (1) JDBC

1,097 阅读2分钟

简介

首先看到了这个议题以后我阅读了sharding jdbc的官方网站。

首先自己搭了一个demo,实现了分库分表,和主从表设置。

1、引入依赖

项目pom.xml文件中,引入sharding-jdbc的依赖

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

2、引入配置文件

# 表要手动创建,不要自动生成
spring.jpa.hibernate.ddl-auto=none
spring.jpa.show-sql=true
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect



# 名称要与db一致
spring.shardingsphere.datasource.names=db0,db1
spring.shardingsphere.datasource.db0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.db0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.db0.jdbc-url=jdbc:mysql://localhost:3306/db0?useUnicode=true&characterEncoding=utf-8
spring.shardingsphere.datasource.db0.username=root
spring.shardingsphere.datasource.db0.password=

spring.shardingsphere.datasource.db1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.bd1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.db1.jdbc-url=jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=utf-8
spring.shardingsphere.datasource.db1.username=root
spring.shardingsphere.datasource.db1.password=

# 如果是SNOWFLAKE主键要为LONG类型
spring.shardingsphere.sharding.tables.user.key-generator.column=user_id
spring.shardingsphere.sharding.tables.user.key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.tables.item.key-generator.column=item_id
spring.shardingsphere.sharding.tables.item.key-generator.type=SNOWFLAKE

#spring.shardingsphere.sharding.default-database-strategy.inline.sharding-column=user_id
#spring.shardingsphere.sharding.default-database-strategy.inline.algorithm-expression=db$->{user_id % 2}
#db$->{0..1}.user_$->{0..1} 无法满足当前情况
spring.shardingsphere.sharding.tables.user.actual-data-nodes=db0.user_0,db1.user_1
spring.shardingsphere.sharding.tables.item.actual-data-nodes=db0.item_0,db1.item_1


# 分库字段
spring.shardingsphere.sharding.tables.user.database-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.tables.item.database-strategy.inline.sharding-column=item_id

# 分表字段
spring.shardingsphere.sharding.tables.user.table-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.tables.item.table-strategy.inline.sharding-column=item_id

# 分表策略,要保证均匀否则会有某些表永远没有数据
spring.shardingsphere.sharding.tables.user.table-strategy.inline.algorithm-expression=user_$->{user_id % 2}
spring.shardingsphere.sharding.tables.item.table-strategy.inline.algorithm-expression=item_$->{item_id % 2}

# 分库策略,要保证均匀否则会有某些表永远没有数据
spring.shardingsphere.sharding.tables.user.database-strategy.inline.algorithm-expression=db$->{ user_id % 2}
spring.shardingsphere.sharding.tables.item.database-strategy.inline.algorithm-expression=db$->{ item_id % 2}

# 打印log
spring.shardingsphere.props.sql.show=true

3、执行sql创建表

DROP TABLE IF EXISTS `user_0`;
CREATE TABLE `user_0` (
  `user_id` bigint DEFAULT NULL,
  `name` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

SET FOREIGN_KEY_CHECKS = 1;

CREATE TABLE `item_0` (
  `item_id` bigint DEFAULT NULL,
  `user_id` bigint DEFAULT NULL,
  `item_name` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

SET FOREIGN_KEY_CHECKS = 1;

在db0创建user_0和item_0表,在db1创建user_1和item_1表

4、编写测试接口

1.编写测试用的类

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long userId;
    private String name;

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

@Entity
public class Item  {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long itemId;
    private Long userId;
    private String itemName;

    public Long getItemId() {
        return itemId;
    }

    public void setItemId(Long itemId) {
        this.itemId = itemId;
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public String getItemName() {
        return itemName;
    }

    public void setItemName(String itemName) {
        this.itemName = itemName;
    }

}

总和的测试类

public class UserItemVO {
    private Long itemId;
    private Long userId;
    private String itemName;
    private String userName;

    public UserItemVO(Long itemId, Long userId, String itemName, String userName) {
        this.itemId = itemId;
        this.userId = userId;
        this.itemName = itemName;
        this.userName = userName;
    }

    public Long getItemId() {
        return itemId;
    }

    public void setItemId(Long itemId) {
        this.itemId = itemId;
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public String getItemName() {
        return itemName;
    }

    public void setItemName(String itemName) {
        this.itemName = itemName;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    @Override
    public String toString() {
        return "UserItemVO{" + "itemId=" + itemId + ", userId=" + userId + ", itemName='" + itemName + '''
            + ", userName='" + userName + ''' + '}';
    }
}

2.编写测试用controller

@GetMapping("/insert")
public void get(){
     for (int i = 0; i < 10; i++) {
         User user = new User();
        user.setName("my name is " + i);
       //  user.setUserId(i+99L);
         User userResult = userRepository.save(user);
         Item u = new Item();
        //u.setUserId(userResult.getUserId());
         u.setItemName("my item is " + i);
         itemRepository.save(u);
     }
     List<User> all1 = userRepository.findAll();
     List<Item> all  = itemRepository.findAll();
     all1.forEach(System.out::println);
     all.forEach(System.out::println);
   //  return all;
   List<UserItemVO> bySql = userRepository.findBySql();
    bySql.forEach(System.out::println);
    return bySql;
}

5、 测试结果

向item插入10条数据, item_name分别为从1到10 ,user_id采用雪花算法生成。

  • 结果: item_name 为2,4,6,8,10的数据插入到 db0, item_name 为1,3,5,7,9的数据插入到 db1。

6、 代码地址和讨论

github.com/a58492906/s…,项目我上传到了github, 在加解密的这个部分我遭遇了难点,没有在自己的demo上面实现,然后通过了群里的讨论,我重新编译了昨天下载的sharding源码的example部分,研究了example里面实现加密解密的部分代码

遇到 Unable to load authentication plugin 'caching_sha2_password'这个异常,在mysql里面重新设置以后解决。

第一天主要花了太多时间在自己的demo上,使用了spring的sharding-starter, 但是这个stater的版本只到4.1.1,好像导致了一些异常,切换到官方的example以后就解决了。