Spring Boot开发—— 实现订单号生成逻辑
文章目录
- 1. UUID
- 2. 数据库序列或自增ID
- 3. 时间戳 + 随机数/序列
- 4. 分布式唯一ID生成方案
几种常见的解决方案
- UUID 实例代码
- 数据库序列或自增ID
- 时间戳 + 随机数/序列
- 分布式唯一ID生成方案
- Snowflake ID结构
- 类定义和变量初始化
- 构造函数
- ID生成方法
- 辅助方法
在 Spring Boot
中设计一个订单号生成系统时,需考虑生成的订单号的唯一性、可扩展性及业务相关性。以下是几种常见的解决方案及相应的示例代码:
1. UUID
使用 UUID
生成唯一的订单号,形式为 8-4-4-4-12
的字符串,例如 123e4567-e89b-12d3-a456-426614174000
。优点是简单,缺点是较长且不易记忆。
实例代码
import java.util.UUID;public class UUIDGenerator {public static String generateUUID() {return UUID.randomUUID().toString();}public static void main(String[] args) {System.out.println("Generated UUID: " + generateUUID());}
}
2. 数据库序列或自增ID
利用数据库的序列或自增ID
生成唯一的订单号,常见于单体应用。
实例代码
@Entity
public class Order {@Id@GeneratedValue(strategy = GenerationType.AUTO)private Long id;// 其他属性
}
数据库示例
- PostgreSQL:
CREATE SEQUENCE order_id_seq START WITH 1 INCREMENT BY 1;
CREATE TABLE orders (order_id bigint NOT NULL DEFAULT nextval('order_id_seq'), order_data text);
- MySQL:
CREATE TABLE orders (order_id INT AUTO_INCREMENT, order_data TEXT, PRIMARY KEY (order_id));
3. 时间戳 + 随机数/序列
结合时间戳与随机数生成订单号,增强可读性与业务相关性。
实例代码
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ThreadLocalRandom;public class OrderNumberGenerator {private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");private static final int RANDOM_NUM_BOUND = 10000;public static String generateOrderNumber(String prefix) {String timestamp = dateFormat.format(new Date());int randomNumber = ThreadLocalRandom.current().nextInt(RANDOM_NUM_BOUND);return prefix + timestamp + String.format("%04d", randomNumber);}public static void main(String[] args) {System.out.println("Generated Order Number: " + generateOrderNumber("ORD"));}
}
4. 分布式唯一ID生成方案
使用 Snowflake
算法生成唯一 ID
,其中包含时间戳、数据中心ID
、机器ID
和序列号,支持分布式系统中的 ID
唯一性和有序性。
Snowflake ID 结构
- 1 位符号位
- 41 位时间戳
- 10 位数据中心 ID 和机器 ID
- 12 位序列号
实现示例
public class SnowflakeIdGenerator {private long datacenterId; // 数据中心IDprivate long machineId; // 机器IDprivate long sequence = 0L; // 序列号private long lastTimestamp = -1L; // 上一次时间戳private final long twepoch = 1288834974657L;private final long datacenterIdBits = 5L;private final long machineIdBits = 5L;private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);private final long maxMachineId = -1L ^ (-1L << machineIdBits);private final long sequenceBits = 12L;private final long machineIdShift = sequenceBits;private final long datacenterIdShift = sequenceBits + machineIdBits;private final long timestampLeftShift = sequenceBits + machineIdBits + datacenterIdBits;private final long sequenceMask = -1L ^ (-1L << sequenceBits);public SnowflakeIdGenerator(long datacenterId, long machineId) {if (datacenterId > maxDatacenterId || datacenterId < 0) {throw new IllegalArgumentException("datacenterId can't be greater than %d or less than 0");}if (machineId > maxMachineId || machineId < 0) {throw new IllegalArgumentException("machineId can't be greater than %d or less than 0");}this.datacenterId = datacenterId;this.machineId = machineId;}public synchronized long nextId() {long timestamp = System.currentTimeMillis();if (timestamp < lastTimestamp) {throw new RuntimeException("Clock moved backwards. Refusing to generate id");}if (lastTimestamp == timestamp) {sequence = (sequence + 1) & sequenceMask;if (sequence == 0) {timestamp = tilNextMillis(lastTimestamp);}} else {sequence = 0L;}lastTimestamp = timestamp;return ((timestamp - twepoch) << timestampLeftShift) |(datacenterId << datacenterIdShift) |(machineId << machineIdShift) |sequence;}private long tilNextMillis(long lastTimestamp) {long timestamp = System.currentTimeMillis();while (timestamp <= lastTimestamp) {timestamp = System.currentTimeMillis();}return timestamp;}
}
下面是对这段代码的逐行解释:
类定义和变量初始化
- private long datacenterId; 定义数据中心ID。
- private long machineId; 定义机器ID。
- private long sequence = 0L; 序列号,用于同一毫秒内生成多个ID时区分这些ID。
- private long lastTimestamp = -1L; 上一次生成ID的时间戳。
以下是Snowflake算法的一些关键参数:
- private final long twepoch = 1288834974657L; 系统的起始时间戳,这里是Snowflake算法的作者选择的一个固定的时间点(2010-11-04 09:42:54.657 GMT)。
- private final long datacenterIdBits = 5L; 数据中心ID所占的位数。
- private final long machineIdBits = 5L; 机器ID所占的位数。
- private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); 数据中心ID的最大值,这里通过位运算计算得出。
- private final long maxMachineId = -1L ^ (-1L << machineIdBits); 机器ID的最大值,同样通过位运算得出。
- private final long sequenceBits = 12L; 序列号占用的位数。
以下是一些用于位运算的参数,用于计算最终的ID:
- private final long machineIdShift = sequenceBits; 机器ID的偏移位数。
- private final long datacenterIdShift = sequenceBits + machineIdBits; 数据中心ID的偏移位数。
- private final long timestampLeftShift = sequenceBits + machineIdBits + datacenterIdBits; 时间戳的偏移位数。
- private final long sequenceMask = -1L ^ (-1L << sequenceBits); 用于保证序列号在指定范围内循环。
构造函数
构造函数SnowflakeIdGenerator(long datacenterId, long machineId)接收数据中心ID和机器ID作为参数,并对这些参数进行校验,确保它们在合法范围内。
ID生成方法
public synchronized long nextId()是生成ID的核心方法,使用synchronized保证线程安全。
- 首先获取当前时间戳。
- 如果当前时间戳小于上一次生成ID的时间戳,抛出异常,因为时钟回拨会导致ID重复。
- 如果当前时间戳等于上一次的时间戳(即同一毫秒内),通过增加序列号生成不同的ID;如果序列号溢出(超过最大值),则等待到下一个毫秒。
- 如果当前时间戳大于上一次的时间戳,重置序列号为0。
- 最后,将时间戳、数据中心ID、机器ID和序列号按照各自的偏移量左移,然后进行位或运算,组合成一个64位的ID。
辅助方法
private long tilNextMillis(long lastTimestamp)是一个辅助方法,用于在序列号溢出时等待直到下一个毫秒。
相关文章:
Spring Boot开发—— 实现订单号生成逻辑
文章目录 1. UUID2. 数据库序列或自增ID3. 时间戳 随机数/序列4. 分布式唯一ID生成方案 几种常见的解决方案 UUID 实例代码数据库序列或自增ID时间戳 随机数/序列分布式唯一ID生成方案 Snowflake ID结构类定义和变量初始化构造函数ID生成方法辅助方法 在 Spring Boot 中设计…...
React中Redux的基本用法
Redux是React中使用较多的状态管理库,这篇文章主要介绍了Redux的基本用法,快来看看吧 首先我们需要新建一个React项目,我使用的ReactTS,文件结构如下 Redux的相关使用主要在store文件中 Store:存储整个应用的状态Act…...
unity3d————基础篇小项目(设置界面)
代码示例: 设置界面 using System.Collections; using System.Collections.Generic; using UnityEngine;public class SettingPanel : BasePanel<SettingPanel> {public UIButton btnClose;public UISlider sliderMusic;public UISlider sliderSound;public…...
推荐几个 VSCode 流程图工具
Visual Studio Code(简称VSCode)是一个由微软开发的免费、开源的代码编辑器。 VSCode 发布于 2015 年,而且很快就成为开发者社区中广受欢迎的开发工具。 VSCode 可用于 Windows、macOS 和 Linux 等操作系统。 VSCode 拥有一个庞大的扩展市…...
用java和redis实现考试成绩排行榜
一、引言 在各类考试场景中,无论是学校里的学业测试,还是线上培训课程的考核,亦或是各类竞赛的选拔,成绩排行榜都是大家颇为关注的一个元素。它不仅能直观地展示考生之间的成绩差异,激发大家的竞争意识,还能…...
hhdb数据库介绍(9-24)
计算节点参数说明 failoverAutoresetslave 参数说明: PropertyValue参数值failoverAutoresetslave是否可见是参数说明故障切换时,是否自动重置主从复制关系默认值falseReload是否生效否 参数设置: <property name"failoverAutor…...
HDMI数据传输三种使用场景
视频和音频的传输 在HDMI传输音频中有3种方式进行传输,第一种将音频和视频信号被嵌入到同一数据流中,通过一个TMDS(Transition Minimized Differential Signaling)通道传输。第二种ARC。第三张种eARC。这三种音频的传输在HDMI线中…...
unigui 登陆界面
新建项目,因为我的Main页面做了其他的东西,所以我在这里新建一个form File -> New -> From(Unigui) -> 登录窗体 添加组件:FDConnection,FDQuery,DataSource,Unipanel和几个uniedit,…...
无人机 PX4飞控 | CUAV 7-Nano 飞行控制器介绍与使用
无人机 PX4飞控 | CUAV 7-Nano 飞行控制器介绍与使用 7-Nano简介硬件参数接口定义模块连接供电部分遥控器电机 固件安装 7-Nano简介 7-Nano是一款针对小型化无人系统设备研发的微型自动驾驶仪。它由雷迅创新自主研发和生产,其创新性的采用叠层设计,在极…...
安装spark
spark依赖java和scale。所以先安装java,再安装scale,再是spark。 总体教程跟着这个链接 我跟着这个教程走安装java链接,但是有一些不同,原教程有一些错误,在环境变量设置的地方。 java 首先下载jdk。 先看自己的环境…...
佛山三水戴尔R740服务器黄灯故障处理
1:佛山三水某某大型商场用户反馈一台DELL PowerEdge R740服务器近期出现了黄灯警告故障,需要冠峰工程师协助检查故障灯原因。 2:工程师协助该用户通过笔记本网线直连到服务器尾部的IDRAC管理端口,默认ip 192.168.0.120 密码一般在…...
大学课程项目中的记忆深刻 Bug —— 一次意外的数组越界
开头 在编程的世界里,每一行代码都像是一个小小的宇宙,承载着开发者的心血与智慧。然而,即便是最精心编写的代码,也难免会遇到那些突如其来的 bug,它们就像是潜伏在暗处的小怪兽,时不时跳出来捣乱。 在我…...
html数据类型
数据类型是字面含义,表示各种数据的类型。在任何语言中都存在数据类型,因为数据是各式各样。 1.数值类型 number let a 1; let num 1.1; // 整数小数都是数字值 // 数字肯定有个范围 正无穷大和负无穷大 // Infinity 正无穷大 // -Infinity 负…...
Kotlin Multiplatform 未来将采用基于 JetBrains Fleet 定制的独立 IDE
近期 Jetbrains 可以说是动作不断,我们刚介绍了 IntelliJ IDEA 2024.3 K2 模式发布了稳定版支持 ,而在官方最近刚调整过的 Kotlin Multiplatform Roadmap 优先关键事项里,可以看到其中就包含了「独立的 Kotlin Multiplatform IDE,…...
Redis中常见的数据类型及其应用场景
五种常见数据类型 Redis中的数据类型指的是 value存储的数据类型,key都是以String类型存储的,value根据场景需要,可以以String、List等类型进行存储。 各数据类型介绍: Redis数据类型对应的底层数据结构 String 类型的应用场景 常…...
代理IP在后端开发中的应用与后端工程师的角色
目录 引言 代理IP的基本概念和工作原理 代理IP在后端开发中的应用 网络爬虫与数据采集 负载均衡与性能优化 安全防护与隐私保护 后端工程师在使用代理IP时面临的挑战 结论 引言 在数字化时代,网络技术的飞速发展极大地推动了各行各业的发展。其中ÿ…...
工作流和流程引擎有什么区别?
在企业的数字化转型中,如何提升效率、优化业务流程是每个管理者都在思考的问题。而在这个过程中,工作流(Workflow)和流程引擎(Process Engine)这两个术语频频出现,成为企业流程自动化和智能化的…...
【SpringBoot】27 拦截器
Gitee仓库 https://gitee.com/Lin_DH/system 介绍 拦截器:拦截器是 Spring 框架提供的核心功能之一,主要用来拦截用户请求,在指定方法前后,根据业务需要执行预先设定的代码。 拦截器允许开发人员提前预定义一些逻辑,…...
AI对开发者的影响,以及传统软件开发 与 AI参与的软件开发区别
AI 大模型,尤其是像 GPT-4、BERT 这样的语言模型,正以深远的影响改变着软件开发流程。传统的软件开发流程通常依赖开发人员进行代码编写、测试、调试等工作,但随着 AI 技术的进步,AI 可以承担越来越多的任务,自动化和优…...
HBase Java基础操作
Apache HBase 是一个开源的、分布式的、可扩展的大数据存储系统,它基于 Google 的 Bigtable 模型。使用 Java 操作 HBase 通常需要借助 HBase 提供的 Java API。以下是一个基本的示例,展示了如何在 Java 中连接到 HBase 并执行一些基本的操作,…...
关于一次开源java spring快速开发平台项目RuoYi部署的记录
关于一次开源java spring快速开发平台项目RuoYi部署的记录 本次因为需要一些练习环境,想要快速搭建一个javaweb 项目作为练习环境,经过查询和实验找到一个文档详细,搭建简单,架构也相对比较新的开源项目RuoYi。 项目介绍…...
【AI编程实战】安装Cursor并3分钟实现Chrome插件(保姆级)
Cursor介绍 https://www.cursor.com/ 一句话介绍:AI代码编辑器,当前最火的AI编程器 软件下载与安装 下载 打开Cursor官网下载,会根据操作系统的差别进行选择 https://www.cursor.com/ 这里下载的内容很小,是个安装器&#x…...
【Chatgpt】如何通过分层Prompt生成更加细致的图文内容
如何通过分层Prompt生成更加细致的图文内容 利用ChatGPT和类似的生成式AI模型,通过分层Prompt设计可以生成更具层次感和细节的图文内容。分层Prompt的核心在于将需求分解成多层次的指令,从宏观到微观逐步细化,最终形成高质量的内容输出。 一…...
中间件--laravel进阶篇
laravel版本11.31,这中间件只有3种,分别是全局中间件,路由中间件,控制器中间件。相比thinkphp8,少了一个应用中间件。 一、创建中间件 laravel创建中间件可以使用命令的方式创建,非常方便。比如php artisan make:middleware EnsureTokenIsValid。EnsureTokenIsValid是中间…...
【vue】vue中.sync修饰符如何使用--详细代码对比
.sync修饰符作用 .sync修饰符是一个语法糖,可以简化父子组件通信操作,当子组件想改变父组件数值时,父组件只需要使用.sync修饰符,子组件使用props接收属性,再使用this.$emit(update:属性, 值);就可以实现子组件更新父…...
repmgr安装及常用运维指令
简介 repmgr 由 EDB 与其他个人和组织的贡献一起开发,安装部署相对较为简单 安装 repmgr官网上传对应的安装到服务器上 安装前/etc/hosts IP映射、始终同步、免密通信本文忽略 repmgr的安装相对较为简单,目前repmgr-5仅仅支持到postgresql-15 postgresql必要参数…...
RedHat系统配置静态IP
1、执行nmtui命令进入字符配置界面如下图所示 2、选择编辑连接进入 3、选择编辑进入后,将IPv4设置为手动模式后,选择显示后进行ip地址、网关、DNS的配置,配置完成后选择确定退出编辑 4、进入主界面后选择启用连接进入后,选择启用&…...
nvm和nrm的安装与使用
NVM相关请跳转: Node版本管理器nvm的安装与使用 nrm 的安装与使用 nrm(NPM Registry Manager)是一个用于管理和切换 NPM 源的工具。它允许你在多个 NPM 源之间快速切换,以提高包管理的速度和效率。以下是 nrm 的安装和使用方法&…...
10大核心应用场景,解锁AI检测系统的智能安全之道
随着工业化和自动化的快速推进,高风险作业场景的安全管理需求日益增加。思通数科AI检测系统以深度学习、计算机视觉和多模态数据融合技术为基础,通过智能化监控和实时反馈,为企业提供全面的作业安全和流程管理解决方案。本文将详细解读该系统…...
香豆烤馍:传统美食中的烟火记忆
食家巷香豆烤馍,承载着甘肃人的乡愁与记忆。它那朴实的外表下,蕴含着丰富的口感和深厚的文化底蕴。烤馍的制作过程充满了烟火气息。选用优质的面粉,经过发酵、揉制等多道工序,再放入传统的烤炉中慢慢烘烤。这个过程需要经验丰富的…...
白云电子商务网站建设/站长之家爱站网
一、数组转字符串 需要将数组元素用某个字符连接成字符串,示例代码如下: var a, b,c; a new Array(a,b,c,d,e); b a.join(-); //a-b-c-d-e //使用-拼接数组元素 c a.join(); //abcde 二、字符串转数组 实现方法为将字符串按某个字符切割成若干个字符…...
wordpress注册验证邮箱/百度软件商店下载安装
如图所示的二叉树表达式: ab*(c-d)-e/f 若先序遍历此二叉树,按访问结点的先后次序将结点排列起来,其先序序列为: (波兰式,前缀表达式) -a*b-cd/ef 按中序遍历,其中序序列为:ab*c-d-e/f (中缀表达式) 按后序遍历,其后序序列为:abcd-*ef/- (逆…...
云南网站建设哪家强/新品上市的营销方案
""" 1. os和sys都是干什么的? 2. 你工作中都用过哪些内置模块? 3. 有没有用过functools模块? """ #sys模块主要是用于提供对python解释器相关的操作 #os模块是Python标准库中的一个用于访问操作系统功能的模块…...
网站建设需要用到什么/sem广告投放是做什么的
React团队推出了一款新工具,希望帮助开发人员减轻新建React应用所引发的痛苦。 在一篇博文中,Dan Abramov介绍了Create React App。该工具让开发人员可以使用一行命令新建一个React应用程序——包括其构建过程和依赖。这是官方支持的一种React应用程序创…...
做网站需要什么人员/电商运营怎么自学
题意描述: 给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 注意,返回任意的子集,所以与之前的题目在终止条…...
深圳网站建设合同/长沙网站设计
原理:tilepro36外接pcie接口的fpga板卡,通过中断的方式通知系统数据接收完毕现象:由于是高速数据采集,pcie中断次数较多,正常情况下每秒7000次左右,不知道网卡中断次数能达到多少,但是有时上电启…...