shardingjdbc分库分表----自定义生成主键

本文介绍了如何在ShardingSphere中实现自定义主键策略,通过SPI机制创建OrderByRedisKeyGenerator类,结合Redis实现基于日期的全局唯一订单编号生成,用于分库分表的主键分配。同时提醒读者,尽管分库分表操作简单,但需谨慎考虑其带来的复杂性,如数据迁移、分布式事务等问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

shardingjdbc分库分表----自定义生成主键

每天多学一点点~
话不多说,这就开始吧…

1.前言

好久没写博客了,主要是新入职的公司太忙,被996摧残了两个多月之后,再也不想去大厂了。。。最近滴滴出事,隔壁的T3出行开始007了好像,资本是真的可怕,手动狗头。。。

吐槽完毕,今天正好闲暇,之前写过一篇 ShardingSphere分库分表----取模和按日期分表,用的是雪花算法作为主键。但有时我们需要清晰可见的主键,比如按照入库时间这样的,所以这次介绍一下在sharding中如何自定义主键策略。

2. proerties配置文件

书接上回,pom依赖和上文都一样。
application-time.properties配置文件

#  =====================  db 以 订单id 取模  table 以 订单创建时间 分库 ===================================================
#配置数据源 boke_1 boke_2
spring.shardingsphere.datasource.names=b0,b1
#默认数据源是b0
spring.shardingsphere.sharding.default-data-source-name=b0

# boke_0 数据源配置
spring.shardingsphere.datasource.b0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.b0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.b0.jdbc-url=jdbc:mysql://localhost:3306/boke_0?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai&relaxAutoCommit=true&zeroDateTimeBehavior=convertToNull
spring.shardingsphere.datasource.b0.username=root
spring.shardingsphere.datasource.b0.password=root

# boke_1 数据源配置
spring.shardingsphere.datasource.b1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.b1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.b1.jdbc-url=jdbc:mysql://localhost:3306/boke_1?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai&relaxAutoCommit=true&zeroDateTimeBehavior=convertToNull
spring.shardingsphere.datasource.b1.username=root
spring.shardingsphere.datasource.b1.password=root


spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=b$->{0..1}.t_order_$->{2020..2021}_$->{1..12}
# 自定义 分片算法
# 分库分片健      database-strategy 数据库策略
spring.shardingsphere.sharding.tables.t_order.database-strategy.standard.sharding-column=order_id
# 自定义 分片 策略
spring.shardingsphere.sharding.tables.t_order.database-strategy.standard.precise-algorithm-class-name=com.boke.order.sharding.time.DBShardingAlgorithm
#                  table-strategy   表 的 策略
spring.shardingsphere.sharding.tables.t_order.table-strategy.standard.sharding-column=create_time
spring.shardingsphere.sharding.tables.t_order.table-strategy.standard.precise-algorithm-class-name=com.boke.order.sharding.time.TableShardingAlgorithm



###########使用SNOWFLAKE算法生成主键
#spring.shardingsphere.sharding.tables.t_order.key-generator.column=order_id
#spring.shardingsphere.sharding.tables.t_order.key-generator.type=SNOWFLAKE
#  雪花算法的workId  机器为标识 0-1024
#spring.shardingsphere.sharding.tables.t_order.key-generator.props.worker.id=123



############ 使用自定义主键 spi 机制 ############# com.boke.order.spi.OrderByRedisKeyGenerator
spring.shardingsphere.sharding.tables.t_order.key-generator.column=order_id
spring.shardingsphere.sharding.tables.t_order.key-generator.type=CUSTOM
spring.shardingsphere.sharding.tables.t_order.key-generator.props.redis.prefix=order:id:prefix:
spring.shardingsphere.sharding.tables.t_order.key-generator.props.worker.id=123

3. spi自定义主键生成的类

在上面的proerties中,定义了
props.redis.prefix=order🆔prefix:

props.worker.id=123
我们通过spi机制,写一个自定义生成的类,代码如下:

  1. 在META-INF/services 下新建org.apache.shardingsphere.spi.keygen.ShardingKeyGenerator
    在这里插入图片描述

  2. OrderByRedisKeyGenerator类实现

package com.boke.order.spi;

import com.boke.order.BokeOrderApplication;
import com.boke.order.utils.RedisOpsUtil;
import com.boke.order.utils.SpringBeanFactory;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.spi.keygen.ShardingKeyGenerator;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;
import java.util.concurrent.TimeUnit;

/**
 * ,;,,;
 * ,;;'(    社
 * __      ,;;' ' \   会
 * /'  '\'~~'~' \ /'\.)  主
 * ,;(      )    /  |.     义
 * ,;' \    /-.,,(   ) \    码
 * ) /       ) / )|    农
 * ||        ||  \)
 * (_\       (_\
 *
 * @author :zjq
 * @date :Created in 2021/07/11 13:55
 * @version: V1.0
 * @slogan: 天下风云出我辈,一入代码岁月催
 * @description: 全局唯一主键生成器【分库分表专用】
 **/
@Slf4j
public class OrderByRedisKeyGenerator implements ShardingKeyGenerator {

    // 写法一

//    @Getter
//    private final String type = "CUSTOM";

//    @Getter
//    @Setter
//    private Properties properties = new Properties();


    // 写法 二

    @Override
    public String getType() {
        return "CUSTOM";
    }

    // 不需要,sharding 底层帮你做了  否则你想添加其他的东西
    // 对应  spring.shardingsphere.sharding.tables.t_order.key-generator.props.redis.prefix
    /**
     *  不需要,sharding 底层帮你做了  否则你想添加其他的东西
     *  对应  spring.shardingsphere.sharding.tables.t_order.key-generator.props.redis.prefix 配置
     *  至于为何:
     *  源码追溯: org.apache.shardingsphere.api.config.sharding.KeyGeneratorConfiguration
     *
     */
    private Properties properties = new Properties();

    @Override
    public Properties getProperties() {
        return properties;
    }

    @Override
    public void setProperties(Properties properties) {
        this.properties = properties;
    }


    /**
     * 生成18位订单编号:8位日期+3位平台ID+7位以上自增id
     * 需在分表策略当中配置如下属性
     * spring.shardingsphere.sharding.tables.t_order.key-generator.column=id
     * spring.shardingsphere.sharding.tables.t_order.key-generator.type=CUSTOM
     * spring.shardingsphere.sharding.tables.t_order.key-generator.props.worker.id=123
     * spring.shardingsphere.sharding.tables.t_order.key-generator.props.redis.prefix=order:id:prefix:
     */
    @Override
    public Comparable<?> generateKey() {
        StringBuilder sb = new StringBuilder();
        RedisOpsUtil redisOpsUtil = SpringBeanFactory.getBean("redisOpsUtil");

        String date = new SimpleDateFormat("yyyyMMdd").format(new Date());
        String key = properties.getProperty("redis.prefix") + date;
        //增长值
        Long increment = null;
        if (redisOpsUtil.hasKey(key)) {
            increment = redisOpsUtil.incr(key, 1);
        } else {
            increment = redisOpsUtil.incr(key, 1);
            redisOpsUtil.expire(key, 24, TimeUnit.HOURS);
        }
        sb.append(date);
        sb.append(String.format("%03d", Integer.parseInt(properties.getProperty("worker.id"))));
        String incrementStr = increment.toString();
        if (incrementStr.length() <= 7) {
            sb.append(String.format("%07d", increment));
        } else {
            sb.append(incrementStr);
        }
        return Long.parseLong(sb.toString());
    }


}

其中,Properties 类sharding底层帮你封装了,会帮我们从properties配置文件中获取以
spring.shardingsphere.sharding.tables.t_order.key-generator.props. 开头的内容,即
redis.prefix=order🆔prefix: 和 worker.id=123,然后通过redis的incr院子操作获取自增的数,按照日期进行拼接,获取我们想要的主键id。

如果有其他的业务需求,也可以根据实际情况自己定制。

分库分表用起来虽然简单,但是能不能还是尽量别分,从业务角度考虑如何不拆分。分了之后,数据迁移,分布式事务,某些sql不支持,mybaits的批量插入等等都要考虑进去。

4. 结语

世上无难事,只怕有心人,每天积累一点点,fighting!!!

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值