首页 > 其他分享 >开源通用高性能的分布式id序列组件

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

时间:2023-06-30 22:44:42浏览次数:43  
标签:obullxl sequence ntSequence long 开源 序列 id 分布式

原文地址: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序列类型,但是无需为每个序列创建序列,因此更简单):

image

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

  • 通用性:仅依赖一张序列数据表,JDBC支持的数据库均可使用,包括SQLite、MySQL、Oracle、OceanBase等。
  • 高性能:本地缓存一个序列区间,缓存使用完之前无DB交互;缓存的区间可设置,区间越大,DB访问越少,性能越高。
  • 分布式:受益于集中式的序列数据表,保证了序列全局唯一。

分布式id序列组件设计

组件接口设计

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

/**
 * Author: [email protected]
 * 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);
}

组件可控参数

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

  • id序列数据表名:默认值为nt_sequence;但对于不同的业务,对数据表名有要求规范(如:表名前置等),因此序列数据表名可设置
  • id序列起始值:默认值为1,即序列值从1开始递增;但对于存量业务,id值起始值需要比存量最大值要大,否则容易重复
  • id序列最大值:默认值为99999999,序列值递增到最大值,则循环从起始值开始
  • 序列更新重试次数:默认值为10,当缓存序列用尽,需要查询和更新序列数据表,比较存在网络通讯和DB操作,不可避免存在异常失败,失败后会进行重试
  • 序列缓存大小:默认值为1000,值越大,访问DB越少,性能越高,序列的连续性越差(如:缓存大小为1000,当序列用到400时,服务器重启了,那么401~1000直接的序列就丢失了);相反,值越小,访问DB越多,性能越低,序列的连续性越好。
/**
 * 属性-数据源
 */
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步即可:

  • 第一步:在项目源代码的根pom.xml中,设置仓库地址:
<repositories>
   <repository>
      <id>Gitee-obullxl</id>
      <url>https://gitee.com/obullxl/maven-repository/master/repository</url>
   </repository>
</repositories>
  • 第二步:引用JAR包,仅需要依赖本JAR包,无其他JAR包依赖:
<dependency>
    <groupId>cn.ntopic</groupId>
    <artifactId>sequence-jdbc</artifactId>
    <version>1.0.1</version>
</dependency>

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

// 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`默认序列ID
long 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序列测试用例

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

标签:obullxl,sequence,ntSequence,long,开源,序列,id,分布式
From: https://www.cnblogs.com/obullxl/p/NTopic2023062101.html

相关文章

  • PID 的搜索算法(PSA)附matlab代码
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • 使用ADB轻松管理Android设备的调试和应用管理
    AndroidDebugBridge(ADB)是一个强大的命令行工具,可用于管理和调试Android设备。1.ADBWiFi调试ADBWiFi调试允许您通过无线网络连接进行设备调试,而无需使用USB连接。以下是进行ADBWiFi调试的步骤:确保您的Android设备与计算机连接在同一网络下。通过USB将设备与计算机连接,并确......
  • 让开源项目从易用到好用 | 亚马逊的开源文化
    亚马逊的领导力准则是亚马逊文化的核心,它如同亚马逊的DNA融入贯穿每一个重要决策,深深影响着每一位亚麻人、影响着每一位亚马逊的客户、合作伙伴以及每一位亚马逊云科技的构建者。同时,亚马逊的领导力准则对亚马逊与开源的互动方式也产生着深远的影响。亚马逊云科技开发者社区......
  • QUuid
    QUuid #include<QUuid>  PublicTypesenumStringFormat {WithBraces,WithoutBraces,Id128}enumVariant {VarUnknown,NCS,DCE,Microsoft,Reserved}enumVersion {VerUnknown,Time,EmbeddedPOSIX,Name,...,Sha1}PublicFunction......
  • Android面经:小厂被diss到自闭,“试水”大厂竟收3份offer
    写在最前面:有时候某人的放弃,将会成就你更好的选择!刚开始面试的时候我真的是处处碰壁,面一家挂一家,面完之后怀疑自我,是不是自己真的太菜了找不到工作,还是真的是像网上所焦虑的那样,Android开发真的是要凉了?这次跳槽经历让我明白,工作本身就是双向选择,一家不行再换一家,总有合适的,千万不......
  • 【八】MySQL数据库之数据库IDE与pymysql模块
    【八】MySQL数据库之数据库IDE与pymysql模块数据库IDE与pymysql模块【一】IDE工具介绍生产环境还是推荐使用mysql命令行但为了方便我们测试可以使用IDE工具在此我们推荐使用Navicat软件或pycharm来连接数据库这样就能更详细直观地查询数据掌握:#1.测试+链接数据......
  • idea的使用技巧
    查找快捷键介绍Ctrl+F在当前文件进行文本查找Ctrl+R在当前文件进行文本替换Shift+Ctrl+F在项目进行文本查找Shift+Ctrl+R在项目进行文本替换Shift+Shift快速搜索Ctrl+N查找classCtrl+Shift+N查找文件Ctrl+Shift+Alt+......
  • IDEA工具使用
    Ctrl+Alt+h表示查看当前方法的实现类或者说当前类的继承关系Ctrl+Alt+b表示当前方法有哪些实现,查看类或方法中的实现,或者使用Ctrl+Alt+鼠标左键......
  • 农业副业产品求购供应发布市场行情VIP会员公众号小程序开源版开发
    农业副业产品求购供应发布市场行情VIP会员公众号小程序开源版开发后台一键同步全国近200家农产品批发市场商品包括,蔬菜、水果、水产、粮油和农副产品等的价格。前端VIP权益功能,开通VIP会员后,可以开启VIP会员标识。可无限制查看全国市场;可无限制查看全国农产品价格;可以无限制搜索......
  • VideoCapture
    fromxgoeduimportXGOEDUimporttime#实例化eduXGO_edu=XGOEDU()XGO_edu.lcd_text(50,50,'hello',color=(255,0,0),fontsize=50)time.sleep(2)importcv2importnumpyasnp#打开摄像头cap=cv2.VideoCapture(0)cap.set(3,320)cap.set(4,240)whi......