我是怎么设计一个订单号生成策略的(库存系统)


一、背景

最近我在做一套自研的库存管理系统,其中有一个看似简单、实则很关键的功能:订单号生成策略

订单号不仅要全局唯一,还要有一定的可读性业务含义,比如能一眼看出是入库单还是出库单、是哪个用户、什么时间生成的。这样在后续查日志、对账、排查问题的时候才更方便。

市面上虽然有很多现成的 ID 生成方案,比如 UUID、Snowflake、Leaf 等等,但它们都有一个共同的问题:没有业务语义

比如这个订单号到底是入库单还是出库单?用户是谁?哪天生成的?看不出来。

所以,我决定自己设计一个订单号生成策略,结合 Redis、时间戳、业务标识和用户信息,实现一个既唯一、又可读、还易维护的方案。


二、我遇到的问题

在设计过程中,我遇到了几个关键问题:

  1. 如何保证订单号全局唯一?
  2. 怎么让订单号有业务含义?
  3. 如何支持分布式部署?
  4. Redis 生成自增ID会不会成为瓶颈?
  5. 如何避免 Redis Key 堆积?

带着这些问题,我开始一步步设计我的订单号生成逻辑。


三、我是怎么做的?

我最终设计了一个订单号结构如下:

[业务码][机器码][用户码][日期][自增ID]

每个字段的含义如下:

字段长度示例说明
业务码2位RK、CK入库(RK)、出库(CK)
机器码2位01、02表示部署节点
用户码6位000123用户ID后6位
日期8位20250719格式为YYYYMMDD
自增ID6位000001每天从1开始递增

示例订单号:

RK0100012320250719000001
  • RK:入库订单
  • 01:机器编号
  • 000123:用户ID后6位
  • 20250719:订单生成日期
  • 000001:当天该用户该业务类型的第一个订单

四、技术实现细节

1. 使用 Redis 生成自增ID

我用 Redis 的 INCR 命令来生成每天的自增ID,Key 的格式如下:

order:${businessType}:${date}:${userCode}

例如:

INCR order:RK:20250719:000123

这样可以保证:

  • 同一用户、同一天、同一业务类型的订单号唯一
  • 每天自动重置计数,避免ID无限增长

2. Java 实现代码

public class OrderNoGenerator {private RedisTemplate<String, String> redisTemplate;public OrderNoGenerator(RedisTemplate<String, String> redisTemplate) {this.redisTemplate = redisTemplate;}public String generateOrderNo(String businessType, int machineId, long userId) {// 1. 业务类型(2位)String bizCode = businessType;// 2. 机器ID(2位)String machineCode = String.format("%02d", machineId);// 3. 用户ID(6位)String userCode = String.format("%06d", userId % 1000000); // 截取后6位// 4. 当前日期(8位)String dateCode = LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE);// 5. Redis 自增ID(6位)String redisKey = String.format("order:%s:%s:%s", bizCode, dateCode, userCode);Long incrId = redisTemplate.opsForValue().increment(redisKey);String incrCode = String.format("%06d", incrId);// 6. 组装订单号return bizCode + machineCode + userCode + dateCode + incrCode;}
}

3. Redis Key 管理与清理

为了避免 Redis Key 无限增长,我加了一个定时任务,每天凌晨清理前一天的 Key:

@Scheduled(cron = "0 0 0 * * ?")
public void clearYesterdayOrderKeys() {String yesterday = LocalDate.now().minusDays(1).format(DateTimeFormatter.BASIC_ISO_DATE);Set<String> keys = redisTemplate.keys("order:*:" + yesterday + ":*");if (keys != null && !keys.isEmpty()) {redisTemplate.delete(keys);}
}

五、难点与优化点

难点:

  1. 如何保证订单号唯一性?
    答案是:Redis + 业务类型 + 时间 + 用户ID组合,保障唯一。

  2. 如何避免 Redis 成为瓶颈?
    Redis 的 INCR 是原子操作,性能很好,但为了进一步优化,也可以采用“分段缓存”机制,比如一次取100个ID本地缓存使用。

  3. 如何让订单号具备可读性?
    通过字段拼接,让订单号包含业务类型、用户、时间等信息,方便日志追踪。

优化建议:

  • 分段自增机制:减少 Redis 调用频率
  • 用户ID压缩算法:如 CRC32 或 MurmurHash,生成更短的用户码
  • 日志与监控:记录生成的订单号,异常时自动报警
  • 多机部署支持:通过机器码区分不同节点,避免冲突

六、实际效果如何?

这套订单号生成策略在我们系统中上线后,运行稳定,效果不错:

  • 订单号唯一性得到保障,未出现重复
  • 日志追踪、对账、排查问题都变得容易
  • Redis 性能良好,未出现瓶颈
  • 支持多节点部署,适配分布式环境

七、总结

通过结合 Redis 自增ID、业务标识、时间戳和用户信息,我实现了一个适合库存系统的订单号生成策略,具有以下优势:

优势说明
唯一性强Redis + 时间 + 用户 + 业务组合保障
可读性高能看出订单类型、用户、时间等信息
结构清晰易于日志追踪和调试
分布式支持机器码支持多节点部署
易于维护支持定时清理、日志记录、异常监控

如果你也在开发类似的库存系统、订单系统或支付系统,不妨参考这套方案。希望这篇文章能对你有所帮助!


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/89783.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/89783.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/89783.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

问津集 #1:Rethinking The Compaction Policies in LSM-trees

文章目录引言正文结束语引言 陪女朋友出门&#xff0c;我大概有两个小时左右的空闲时间&#xff0c;遂带上电脑&#xff0c;翻了下论文列表&#xff0c;选择了这篇文章做一个简读。 因为这一年负责时序系统的存储引擎和计算引擎演进&#xff0c;而Compaction又是串联读写的核心…

数据产品结构:从数据接入到可视化的完整架构指南

在数据驱动决策的时代&#xff0c;一套高效的数据产品结构是企业挖掘数据价值的基础。无论是巨头企业自建的完整体系&#xff0c;还是中小企业依赖的第三方工具&#xff0c;其核心逻辑都是实现 “数据从产生到呈现” 的全链路管理。本文将拆解数据产品的五层架构&#xff0c;对…

python学智能算法(二十三)|SVM-几何距离

引言 前序学习文章中&#xff0c;已经探究了电荷超平面的距离计算方法&#xff0c;相关文章为点与超平面的距离。 在这片文章中&#xff0c;我们了解到计算距离的公式&#xff1a; Fmin⁡i1...myi(w⋅xib)F\min_{i1...m}y_{i}(w\cdot x_{i}b)Fi1...mmin​yi​(w⋅xi​b) 计算…

[每日随题11] 贪心 - 数学 - 区间DP

整体概述 难度&#xff1a;1000 →\rightarrow→ 1400 →\rightarrow→ 1600 P3918 [国家集训队] 特技飞行 标签&#xff1a;贪心 前置知识&#xff1a;无 难度&#xff1a;橙 1000 题目描述&#xff1a; 输入格式&#xff1a; 输出格式&#xff1a; 样例输入&#xff1a;…

Elasticsearch 9.x 搜索执行流程(源码解读)

1. 搜索执行流程概述 Elasticsearch的搜索执行是一个分布式过程,涉及协调节点和数据节点之间的多阶段交互 #mermaid-svg-QGh2GjrUKcs5jzQp {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-QGh2GjrUKcs5jzQp .error…

暑期训练8

E. G-C-D, Unlucky!题目要求判断是否存在一个长度为 n 的数组 a&#xff0c;使得p[i] 是 a[0..i] 的前缀 GCDs[i] 是 a[i..n-1] 的后缀 GCD思路前缀 GCD 非递增后缀 GCD 非递减首尾 GCD 一致桥梁条件成立对于每个位置 i&#xff0c;gcd(p[i], s[i1]) 必须等于整个数组的 GCD&am…

深入解析Hadoop HDFS高可用性:原理、故障切换与元数据同步

Hadoop HDFS高可用性(HA)概述在分布式存储领域&#xff0c;Hadoop分布式文件系统(HDFS)作为Hadoop生态系统的核心存储组件&#xff0c;其高可用性(HA)设计一直是架构师们关注的焦点。传统HDFS架构中&#xff0c;NameNode作为单一主节点管理整个文件系统的元数据&#xff0c;这种…

Freertos源码分析:任务创建/删除

任务创建/删除流程1.简介FreeRTOS 中任务创建通过 xTaskCreate() 或 xTaskCreateStatic() 实现。动态创建&#xff08;xTaskCreate&#xff09;会自动分配任务栈和TCB&#xff08;任务控制块&#xff09;&#xff0c;静态创建&#xff08;xTaskCreateStatic&#xff09;需用户预…

warning: _close is not implemented and will always fail

相关问题&#xff1a; 一、undefined reference to _exit undefined reference to ‘end‘ warning: _close is not implemented and will always fail 一、环境&#xff1a; ubuntu24.04实体机、 arm-none-eabi-gcc gcc version 13.2.1 20231009 (15:13.2.rel1-2) 二…

MyBatis之缓存机制详解

MyBatis之缓存机制详解一、MyBatis缓存的基本概念1.1 缓存的核心价值1.2 MyBatis的两级缓存体系二、一级缓存&#xff08;SqlSession级别缓存&#xff09;2.1 工作原理2.2 实战案例&#xff1a;一级缓存演示2.2.1 基础用法&#xff08;默认开启&#xff09;2.2.2 一级缓存失效场…

云服务器搭建自己的FRP服务。为什么客户端的项目需要用Docker启动,服务端才能够访问到?

简单回答&#xff1a;在云服务器搭建FRP服务时&#xff0c;客户端项目用Docker启动并非必需&#xff0c;而是因为Docker的特性简化了配置&#xff1a; Docker通过端口映射&#xff08;如-p 本地端口:容器端口&#xff09;能固定项目对外暴露的端口&#xff0c;减少本地端口冲突…

6 STM32单片机的智能家居安防系统设计(STM32代码+手机APP设计+PCB设计+Proteus仿真)

系列文章目录 文章目录 系列文章目录前言1 资料获取与演示视频1.1 资料介绍1.2 资料获取1.3 演示视频 2 系统框架3 硬件3.1 主控制器3.2 显示屏3.3 WIFI模块3.4 DHT11温湿度传感器3.5 烟雾/燃气传感器模块&#xff1a;MQ-23.6 火焰传感器3.7 门磁模块MC-38 4 设计PCB4.1 安装下…

DevOps落地的终极实践:8大关键路径揭秘!

本文来自腾讯蓝鲸智云社区用户: CanWay当前&#xff0c;DevOps因其能够降低IT运营成本、提高软件质量并加快上市时间的能力而在全球范围内引起广泛关注。它打破了传统软件开发与运营的界限&#xff0c;消除了新功能发布延迟和软件质量下降的障碍。DevOps通过实施持续集成、持续…

react - 根据路由生成菜单

后端返回菜单的格式menuList:[{index: true,name: "",component: "../views/Home",meta: { title: "首页", requiresAuth: true,roles:[user]},},{path: "/admin",name: "admin",meta: { title: "管理页", roles:…

Window延迟更新10000天配置方案

1.点击"开始"菜单&#xff0c;搜索"注册表编辑器"&#xff0c;点击"打开"。2.找到"\HKEY LOCAL MACHINE\SOFTWARE\Microsoft\WindowsUpdate\Ux\Settings"路径。3.右面空白处右键新建一个32位值&#xff0c;命名为FlightSettingsMaxPau…

【OD机试】人民币转换

题目描述 将阿拉伯数字金额转换为中文大写金额格式,需遵循以下规则: 1、 前缀要求:中文大写金额前必须标明“人民币”字样。 2、 用字规范:使用壹、贰、叁、肆、伍、陆、柒、捌、玖、拾、佰、仟、万、亿、元、角、分、零、整等字样。 3、 “整”字规则: 金额到“元”为止…

在ajax中什么时候需要将返回值类型做转换

$.ajax({url: TMSPROC0050/deleteData?accidentIds accidentIds.join(,),type: DELETE,dataType: json,success: function(result) {$(#accidentGrid).datagrid(reload);$.messager.show({title: 成功,msg: result.message})},error: function(result) {$.messager.alert({ti…

Helm常用命令大全(2025最新版)

文章目录Helm常用命令大全&#xff08;2025最新版&#xff09;一、基础命令与环境配置版本与帮助信息安装与升级HelmLinux系统安装版本升级注意事项二、仓库管理命令仓库基础操作OCI仓库支持&#xff08;v3.8新特性&#xff09;三、Chart操作命令Chart创建与打包Chart搜索与下载…

gitlab+jenkins

文章目录架构gitlab和jenkins安装jenkins配置gitlab配置jenkins与gitlab联动参考架构 gitlab和jenkins安装 部署docker 部署jenkins 启动jenkins 用户&#xff1a;admin&#xff0c;对应的密码如下 点击安装自定义推荐的插件 安装gitlab插件 jenkins配置 配置pipline…

Redis字符串操作指南:从入门到实战应用

Redis作为一款高性能的键值存储数据库&#xff0c;其字符串&#xff08;String&#xff09;类型是最基础也最常用的数据类型。它不仅能存储简单的文本信息&#xff0c;还能应对数字计算、二进制数据等多种场景&#xff0c;灵活且高效。接下来&#xff0c;我们就全方位剖析Redis…