美文网首页
spring boot接入sharding-jdbc

spring boot接入sharding-jdbc

作者: engineer_tang | 来源:发表于2022-10-04 09:55 被阅读0次

1. bootstrip.yml配置sharding-jdbc

spring:
  # 配置sharding jdbc数据库
  shardingsphere:
    sharding:
      #未配置分片规则的表将通过默认数据源定位-适用于单库单表,该表无需配置分片规则
      default-data-source-name: ds0
      tables:
        t_shop:
          database-strategy:
            inline:
              # 分库 以 create_by 为分片键,因为分三个库,所以取模 3,虚拟表名为 t_shop
              algorithm-expression: ds$->{create_by % 3}
              sharding-column: create_by
          table-strategy:
            inline:
              # 分表 分片键位id,每个库分为两表,所以取模2
              algorithm-expression: t_shop_00$->{id % 2}
              sharding-column: id
          # 这里由于分库分表字段不相同配置,不然会导致使用create_by 查询找不到相应的表,如果我们分库分表都使用 create_by 则不需要这个配置
          actual-data-nodes: ds$->{0..2}.t_shop_00$->{0..1}
    props:
      sql:
        #是否开启SQL显示,默认值: false
        show: true
    datasource:
      #数据源名称,多数据源以逗号分隔
      names: ds0,ds1,ds2
      ds0:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.jdbc.Driver
        jdbc-url: jdbc:mysql://127.0.0.1:3306/strawberry-shop1?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
        username: root
        password: 123456
      ds1:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.jdbc.Driver
        jdbc-url: jdbc:mysql://127.0.0.1:3306/strawberry-shop2?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
        username: root
        password: 123456
      ds2:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.jdbc.Driver
        jdbc-url: jdbc:mysql://127.0.0.1:3306/strawberry-shop3?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
        username: root
        password: 123456

2. 在pom文件增加sharding-jdbc依赖

        <!-- 实现对 Sharding-JDBC 的自动化配置 -->
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
        </dependency>

3. 准备数据库表

image.png

4. 实现业务代码

image.png

5. 雪花算法ID获取实现

5.1 业务组件

@Component
public class SnowFlakeService {

    Map<String, SnowFlake> snowFlakeHandlerMap = new ConcurrentHashMap<>();
    public long nextId() {
        long dataCenterId = 3L;
        long machineId = 7L;
        return nextId(dataCenterId, machineId);
    }

    public long nextId(final long datacenterId, final long machineId) {
        final long sdatacenterId = datacenterId;
        final long smachineId = machineId;
        final String handler = sdatacenterId + "_" + smachineId;
        SnowFlake snowFlake;
        if (snowFlakeHandlerMap.containsKey(handler)) {
            snowFlake = snowFlakeHandlerMap.get(handler);
            return snowFlake.nextId();
        } else {
            snowFlake = new SnowFlake(datacenterId, machineId);
            snowFlakeHandlerMap.putIfAbsent(handler, snowFlake);
            snowFlake = snowFlakeHandlerMap.get(handler);
            return snowFlake.nextId();
        }
    }
}

5.2 雪花工具类


package com.joe.strawberry.shop.provider.service.impl;

public class SnowFlake {

    /**
     * 起始的时间戳
     */
    private final static long START_STMP = 1480166465631L;

    /**
     * 每一部分占用的位数
     */
    private final static long SEQUENCE_BIT = 12; //序列号占用的位数
    private final static long MACHINE_BIT = 5;   //机器标识占用的位数
    private final static long DATACENTER_BIT = 5;//数据中心占用的位数

    /**
     * 每一部分的最大值
     */
    private final static long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT);
    private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);
    private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);

    /**
     * 每一部分向左的位移
     */
    private final static long MACHINE_LEFT = SEQUENCE_BIT;
    private final static long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;
    private final static long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT;

    private long datacenterId;  //数据中心
    private long machineId;     //机器标识
    private long sequence = 0L; //序列号
    private long lastStmp = -1L;//上一次时间戳

    public SnowFlake(long datacenterId, long machineId) {
        if (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0) {
            throw new IllegalArgumentException("datacenterId can't be greater than MAX_DATACENTER_NUM or less than 0");
        }
        if (machineId > MAX_MACHINE_NUM || machineId < 0) {
            throw new IllegalArgumentException("machineId can't be greater than MAX_MACHINE_NUM or less than 0");
        }
        this.datacenterId = datacenterId;
        this.machineId = machineId;
    }

    /**
     * 产生下一个ID
     *
     * @return
     */
    public synchronized long nextId() {
        long currStmp = getNewstmp();
        if (currStmp < lastStmp) {
            throw new RuntimeException("Clock moved backwards.  Refusing to generate id");
        }

        if (currStmp == lastStmp) {
            //相同毫秒内,序列号自增
            sequence = (sequence + 1) & MAX_SEQUENCE;
            //同一毫秒的序列数已经达到最大
            if (sequence == 0L) {
                currStmp = getNextMill();
            }
        } else {
            //不同毫秒内,序列号置为0
            sequence = 0L;
        }

        lastStmp = currStmp;

        return (currStmp - START_STMP) << TIMESTMP_LEFT //时间戳部分
            | datacenterId << DATACENTER_LEFT       //数据中心部分
            | machineId << MACHINE_LEFT             //机器标识部分
            | sequence;                             //序列号部分
    }

    private long getNextMill() {
        long mill = getNewstmp();
        while (mill <= lastStmp) {
            mill = getNewstmp();
        }
        return mill;
    }

    private long getNewstmp() {
        return System.currentTimeMillis();
    }
}

相关文章

网友评论

      本文标题:spring boot接入sharding-jdbc

      本文链接:https://www.haomeiwen.com/subject/gmzuartx.html