当前位置: 首页 > news >正文

Spring Boot开发—— 实现订单号生成逻辑

文章目录

  • 1. UUID
  • 2. 数据库序列或自增ID
  • 3. 时间戳 + 随机数/序列
  • 4. 分布式唯一ID生成方案

几种常见的解决方案

  1. UUID 实例代码
  2. 数据库序列或自增ID
  3. 时间戳 + 随机数/序列
  4. 分布式唯一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中使用较多的状态管理库&#xff0c;这篇文章主要介绍了Redux的基本用法&#xff0c;快来看看吧 首先我们需要新建一个React项目&#xff0c;我使用的ReactTS&#xff0c;文件结构如下 Redux的相关使用主要在store文件中 Store&#xff1a;存储整个应用的状态Act…...

unity3d————基础篇小项目(设置界面)

代码示例&#xff1a; 设置界面 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&#xff08;简称VSCode&#xff09;是一个由微软开发的免费、开源的代码编辑器。 VSCode 发布于 2015 年&#xff0c;而且很快就成为开发者社区中广受欢迎的开发工具。 VSCode 可用于 Windows、macOS 和 Linux 等操作系统。 VSCode 拥有一个庞大的扩展市…...

用java和redis实现考试成绩排行榜

一、引言 在各类考试场景中&#xff0c;无论是学校里的学业测试&#xff0c;还是线上培训课程的考核&#xff0c;亦或是各类竞赛的选拔&#xff0c;成绩排行榜都是大家颇为关注的一个元素。它不仅能直观地展示考生之间的成绩差异&#xff0c;激发大家的竞争意识&#xff0c;还能…...

hhdb数据库介绍(9-24)

计算节点参数说明 failoverAutoresetslave 参数说明&#xff1a; PropertyValue参数值failoverAutoresetslave是否可见是参数说明故障切换时&#xff0c;是否自动重置主从复制关系默认值falseReload是否生效否 参数设置&#xff1a; <property name"failoverAutor…...

HDMI数据传输三种使用场景

视频和音频的传输 在HDMI传输音频中有3种方式进行传输&#xff0c;第一种将音频和视频信号被嵌入到同一数据流中&#xff0c;通过一个TMDS&#xff08;Transition Minimized Differential Signaling&#xff09;通道传输。第二种ARC。第三张种eARC。这三种音频的传输在HDMI线中…...

unigui 登陆界面

新建项目&#xff0c;因为我的Main页面做了其他的东西&#xff0c;所以我在这里新建一个form File -> New -> From(Unigui) -> 登录窗体 添加组件&#xff1a;FDConnection&#xff0c;FDQuery&#xff0c;DataSource&#xff0c;Unipanel和几个uniedit&#xff0c;…...

无人机 PX4飞控 | CUAV 7-Nano 飞行控制器介绍与使用

无人机 PX4飞控 | CUAV 7-Nano 飞行控制器介绍与使用 7-Nano简介硬件参数接口定义模块连接供电部分遥控器电机 固件安装 7-Nano简介 7-Nano是一款针对小型化无人系统设备研发的微型自动驾驶仪。它由雷迅创新自主研发和生产&#xff0c;其创新性的采用叠层设计&#xff0c;在极…...

安装spark

spark依赖java和scale。所以先安装java&#xff0c;再安装scale&#xff0c;再是spark。 总体教程跟着这个链接 我跟着这个教程走安装java链接&#xff0c;但是有一些不同&#xff0c;原教程有一些错误&#xff0c;在环境变量设置的地方。 java 首先下载jdk。 先看自己的环境…...

佛山三水戴尔R740服务器黄灯故障处理

1&#xff1a;佛山三水某某大型商场用户反馈一台DELL PowerEdge R740服务器近期出现了黄灯警告故障&#xff0c;需要冠峰工程师协助检查故障灯原因。 2&#xff1a;工程师协助该用户通过笔记本网线直连到服务器尾部的IDRAC管理端口&#xff0c;默认ip 192.168.0.120 密码一般在…...

大学课程项目中的记忆深刻 Bug —— 一次意外的数组越界

开头 在编程的世界里&#xff0c;每一行代码都像是一个小小的宇宙&#xff0c;承载着开发者的心血与智慧。然而&#xff0c;即便是最精心编写的代码&#xff0c;也难免会遇到那些突如其来的 bug&#xff0c;它们就像是潜伏在暗处的小怪兽&#xff0c;时不时跳出来捣乱。 在我…...

html数据类型

数据类型是字面含义&#xff0c;表示各种数据的类型。在任何语言中都存在数据类型&#xff0c;因为数据是各式各样。 1.数值类型 number let a 1; let num 1.1; // 整数小数都是数字值 ​ // 数字肯定有个范围 正无穷大和负无穷大 // Infinity 正无穷大 // -Infinity 负…...

Kotlin Multiplatform 未来将采用基于 JetBrains Fleet 定制的独立 IDE

近期 Jetbrains 可以说是动作不断&#xff0c;我们刚介绍了 IntelliJ IDEA 2024.3 K2 模式发布了稳定版支持 &#xff0c;而在官方最近刚调整过的 Kotlin Multiplatform Roadmap 优先关键事项里&#xff0c;可以看到其中就包含了「独立的 Kotlin Multiplatform IDE&#xff0c;…...

Redis中常见的数据类型及其应用场景

五种常见数据类型 Redis中的数据类型指的是 value存储的数据类型&#xff0c;key都是以String类型存储的&#xff0c;value根据场景需要&#xff0c;可以以String、List等类型进行存储。 各数据类型介绍&#xff1a; Redis数据类型对应的底层数据结构 String 类型的应用场景 常…...

代理IP在后端开发中的应用与后端工程师的角色

目录 引言 代理IP的基本概念和工作原理 代理IP在后端开发中的应用 网络爬虫与数据采集 负载均衡与性能优化 安全防护与隐私保护 后端工程师在使用代理IP时面临的挑战 结论 引言 在数字化时代&#xff0c;网络技术的飞速发展极大地推动了各行各业的发展。其中&#xff…...

工作流和流程引擎有什么区别?

在企业的数字化转型中&#xff0c;如何提升效率、优化业务流程是每个管理者都在思考的问题。而在这个过程中&#xff0c;工作流&#xff08;Workflow&#xff09;和流程引擎&#xff08;Process Engine&#xff09;这两个术语频频出现&#xff0c;成为企业流程自动化和智能化的…...

【SpringBoot】27 拦截器

Gitee仓库 https://gitee.com/Lin_DH/system 介绍 拦截器&#xff1a;拦截器是 Spring 框架提供的核心功能之一&#xff0c;主要用来拦截用户请求&#xff0c;在指定方法前后&#xff0c;根据业务需要执行预先设定的代码。 拦截器允许开发人员提前预定义一些逻辑&#xff0c…...

AI对开发者的影响,以及传统软件开发 与 AI参与的软件开发区别

AI 大模型&#xff0c;尤其是像 GPT-4、BERT 这样的语言模型&#xff0c;正以深远的影响改变着软件开发流程。传统的软件开发流程通常依赖开发人员进行代码编写、测试、调试等工作&#xff0c;但随着 AI 技术的进步&#xff0c;AI 可以承担越来越多的任务&#xff0c;自动化和优…...

HBase Java基础操作

Apache HBase 是一个开源的、分布式的、可扩展的大数据存储系统&#xff0c;它基于 Google 的 Bigtable 模型。使用 Java 操作 HBase 通常需要借助 HBase 提供的 Java API。以下是一个基本的示例&#xff0c;展示了如何在 Java 中连接到 HBase 并执行一些基本的操作&#xff0c…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

MMaDA: Multimodal Large Diffusion Language Models

CODE &#xff1a; https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA&#xff0c;它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

工程地质软件市场:发展现状、趋势与策略建议

一、引言 在工程建设领域&#xff0c;准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具&#xff0c;正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案

随着新能源汽车的快速普及&#xff0c;充电桩作为核心配套设施&#xff0c;其安全性与可靠性备受关注。然而&#xff0c;在高温、高负荷运行环境下&#xff0c;充电桩的散热问题与消防安全隐患日益凸显&#xff0c;成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。

1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj&#xff0c;再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列&#xff0c;以便知晓哪些列包含有价值的数据&#xff0c;…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...