开源通用高性能的分布式id序列组件
博客园 2023-07-01 05:39:15

原文地址:https://ntopic.cn/p/2023062101/

分布式id序列说明

业务数据的存储,少不了数据记录的id序列。

id序列(或称序列)的生成方式有很多种,比如当前时间戳、数据库的序列值(Oracle的序列,MySQL的自增ID等)、UUID等方式。


【资料图】

这些生成方式都有一定的局限性,如时间戳在业务量较大时容易重复、Oracle序列和MySQL的自增ID限定了数据库类型(且MySQL的自增ID只能保证单库唯一,在分库分表的场景下也不适用)、UUID容易重复且无法保证递增等。

同时,一般业务数据的id序列通常会带上一些业务信息,比如增加业务标识前缀、增加年月日等信息。业务id序列的处理变得多样,则进一步要求业务id序列的生成通用且高效。

通用分布式id序列组件

为了屏蔽业务获取id序列因数据库类型、分库分表等带来的研发和维护成本,我们把分布式id序列的获取抽取为一个通用组件,对业务统一接口和规范。

通用分布式id序列实现方式有很多,本文主要介绍一种基于数据表的实现方式,通过一张表记录所有的业务序列名和值,业务根据序列名获取下一个序列值(和Oracle序列类型,但是无需为每个序列创建序列,因此更简单):

本方案的设计主要考量点:

分布式id序列组件设计

组件接口设计

组件接口只有1个,就是获取序列:

/** * Author: obullxl@163.com * Copyright (c) 2020-2023 All Rights Reserved. */package cn.ntopic.sequence;/** * 分布式序列服务 * * @author obullxl 2023年06月21日: 新增 */public interface NTSequence {    /**     * 默认序列名称     */    String DEFAULT_SEQUENCE_NAME = "DEFAULT";    /**     * 序列名称最大长度     */    int MAX_SEQUENCE_NAME_LENGTH = 64;    /**     * 获取下一个序列值     *     * @return 获取默认序列的新的唯一的序列值 {@link #DEFAULT_SEQUENCE_NAME}     * @throws IllegalArgumentException 参数非法     */    default long next() {        return this.next(DEFAULT_SEQUENCE_NAME);    }    /**     * 获取下一个序列值     *     * @param sequenceName 序列名称,非空,1~64字符,业务可随意指定(如:用户模块为`USER`,订单模块为`ORDER`等)     * @return 新的唯一的序列值     * @throws IllegalArgumentException 参数非法     */    long next(String sequenceName);}

组件可控参数

在追求通用性和性能的同时,以参数的方式供个性化调控:

/** * 属性-数据源 */private final DataSource ntDataSource;/** * 属性-重试次数 */private int retryTimes = 10;/** * 属性-数据表名 */private String tableName = "nt_sequence";/** * 属性-序列获取步长(即序列缓存大小) */private long step = 1000L;/** * 属性-序列最小值 */private long minValue = 1L;/** * 属性-序列最大值 */private long maxValue = 99999999L;

序列组件使用

目前JAR包已经发布,通过Gitee进行仓库托管,也可直接使用,2步即可:

         Gitee-obullxl      https://gitee.com/obullxl/maven-repository/master/repository   
    cn.ntopic    sequence-jdbc    1.0.1

在业务代码中调用序列组件样例:

// 1. 构建数据源DruidDataSource dataSource = new DruidDataSource();dataSource.setUrl("jdbc:sqlite:/Users/obullxl/CodeSpace/sequence-jdbc/SequenceJDBC.sqlite");dataSource.setDriverClassName("org.sqlite.JDBC");dataSource.setPoolPreparedStatements(false);dataSource.setMaxPoolPreparedStatementPerConnectionSize(-1);dataSource.setTestOnBorrow(true);dataSource.setTestOnReturn(false);dataSource.setTestWhileIdle(true);dataSource.setValidationQuery("SELECT "1" FROM sqlite_master LIMIT 1");// 2. 初始化序列组件NTSequenceImpl ntSequence = new NTSequenceImpl(dataSource);ntSequence.setTableName(tableName);ntSequence.createTable();ntSequence.init();// 3. 获取序列值@Autowire@Qualifier("ntSequence")private NTSequence ntSequence;// 获取`DEFAULT`默认序列IDlong newId1 = ntSequence.next();long newId2 = ntSequence.next();long newId3 = ntSequence.next();// 获取`USER`用户ID:long newUserId1 = ntSequence.next("USER");long newUserId2 = ntSequence.next("USER");long newUserId3 = ntSequence.next("USER");// 获取`ORDER`订单ID:long newOrderId1 = ntSequence.next("ORDER");long newOrderId2 = ntSequence.next("ORDER");long newOrderId3 = ntSequence.next("ORDER");

完整的使用方法,可参数源代码仓库说明文档(README.md):

分布式id序列测试用例

因为代码较大,请直接查看源代码:

猜你喜欢

开源通用高性能的分布式id序列组件

2023-07-01

速讯:【工会送清凉 防暑保安康】“智送清凉”普惠户外劳动者

2023-07-01

世界即时看!官场小说精品大全集:天天向上

2023-07-01

十大太古凶兽_大荒十大凶兽大揭秘

2023-06-30

世界微资讯!怀来县开展安全教育“进校园”活动

2023-06-30

全球短讯!我国首个藏医专用医疗器械产品正式发布

2023-06-30

国家外汇管理局:5月我国国际收支货物和服务贸易进出口规模同比增长1%

2023-06-30

在今年大豆丰产预期暂未被证伪的背景下 远月合约仍然难以具备较大的上行空间

2023-06-30

外汇局:5月我国国际收支货物和服务贸易进出口规模38112亿元,同比增长1%

2023-06-30

西安饮食(000721)6月30日主力资金净买入1503.17万元

2023-06-30

世界关注:《南洋女儿情》南兰为什么离婚?

2023-06-30

2023年国家医保药品目录调整工作方案正式公布|天天精选

2023-06-30

除味剂商品报价动态(2023-06-30)-世界今日报

2023-06-30

焦点快报!致青春电视剧刘奕君陈瑶 熟年郝蕾刘奕君婚姻危机 基本情况讲解

2023-06-30

火花deco罗马音(花火罗马音歌词) 今日报

2023-06-30

热门推荐