如何设计一个能扛住双11并发的订单号生成方案

2024-02-11 18:58

本文主要是介绍如何设计一个能扛住双11并发的订单号生成方案,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

要设计订单号首先需要订单号应该要具备的一些特性:

  1. 唯一性:这绝对是作为订单号最最最基本的特点;

  2. 高并发:并发能力越高越好;

  3. 趋势递增但是不能绝对递增:趋势递增会对现代数据库索引结构更友好,但是不要绝对递增是因为绝对递增的话,很容易暴露你系统每天产生的订单量;

  4. 利于以后的分库分表;

我的订单号方案

技术方案:
timestamp + 类用户ID + 随机数(可选)实现代码:
Long userId = 235689102L;
String last6 = userId<1000000?String.format("%06d", userId):String.valueOf(userId%1000000);
String orderId = System.currentTimeMillis() + last6;

这种方案是否具备上面提到的几个特点呢,让我们一起看一看:

  1. 唯一性:这种方案的订单号只有在同一个用户在同一毫秒内下多个订单才会出现出现,很显然,对于正常的用户行为,是不可能出现重复的,所以满足唯一性。

  2. 高并发:这个设计方案完全不依赖任何第三方服务,只通过一定的规则就能生成。所以这种方案不但高并发,而且零消耗。

  3. 递增性:因为订单号的前一部分是时间戳,所以满足趋势递增。并且,也满足非绝对递增的特性。

  4. 分库分表:假设分库分表因子为订单号最后6位数,那么无论是根据订单ID查询,还是根据用户ID查询,都不会涉及跨库跨表,效率非常高。至于根据商户编号查询商户的订单号,可以参考笔者另一篇文章《分库分表技术演进&最佳实践-修订篇》,有提到解决方案。

通过上面的分析可知,这种方案还是很不错的!而且,这种方案不需要依赖任何第三方服务,需要的硬件成本为零,老板最喜欢呀!当然,如果担心用户ID信息通过订单号暴露,可以先通过某种函数例如hash(userId),然后再生成订单号即可。伪代码如下:

Long userId = 235689102L;
Long hashId = hash(userId);
String last6 = hashId<1000000?String.format("%06d", hashId):String.valueOf(hashId%1000000);
String orderId = System.currentTimeMillis() + last6;
System.out.println(orderId);

 

  • 为什么这种方案利于分库分表?

我们知道作为一个订单表,最核心的查询有3类:根据订单号查询、根据用户ID查询、根据商户号查询,这三类查询占了订单表90%甚至更多的查询量。如果采用的是这里提到的时间戳+类用户ID的方案,那么根据订单号查询和根据用户ID查询都不涉及跨表,效率非常高。请看接下来的分析。

假设订单表按照订单号进行分表,并且分表算法为:hash(last6(orderId))%16,即根据订单号的最后6位数字hash后取模。这样的话,如下几个订单号就会分在同一个表假设t_order_5中,因为这几个订单号最后6位数字完全一样:

1573172799123 141618
1575878423467 141618
1583545280012 141618

然后,这几个订单表都是用户ID为182141618生成的(我们假设hash(182141618)%1000000=141618)。那么用户ID为182141618所生成的订单也会都落在表t_order_5中,因为hash(182141618)%1000000=141618,也就是说,查询条件带有userId=182141618的查询目标表都是t_order_5。事实上,这种方案就是所谓的因子分表法

接下来,我们可以看一下支付宝订单号又是如何设计的。

 

支付宝订单号方案

下面是3个真实的支付宝订单号(空格是为了更直观的看出支付宝订单号的特点):

20191024 2200141625 1404175790
20191025 2200141625 1404414662
20191026 2200141625 1405369921

分析这几个支付宝订单号,我们将其分解为3部分,从而得出支付宝的订单号的特点。你的支付宝订单号同样具备这样的特点:

时间戳 + 类用户ID + 递增的数值

通过对支付宝订单号的分解,我们很容易发现它的方案和前面提到的方案有异曲同工之妙:都有时间戳部分和类用户ID部分,此乃英雄所见略同也,哈哈哈!

这篇关于如何设计一个能扛住双11并发的订单号生成方案的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/700577

相关文章

防止Linux rm命令误操作的多场景防护方案与实践

《防止Linuxrm命令误操作的多场景防护方案与实践》在Linux系统中,rm命令是删除文件和目录的高效工具,但一旦误操作,如执行rm-rf/或rm-rf/*,极易导致系统数据灾难,本文针对不同场景... 目录引言理解 rm 命令及误操作风险rm 命令基础常见误操作案例防护方案使用 rm编程 别名及安全删除

Java使用Javassist动态生成HelloWorld类

《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC

Python实现批量CSV转Excel的高性能处理方案

《Python实现批量CSV转Excel的高性能处理方案》在日常办公中,我们经常需要将CSV格式的数据转换为Excel文件,本文将介绍一个基于Python的高性能解决方案,感兴趣的小伙伴可以跟随小编一... 目录一、场景需求二、技术方案三、核心代码四、批量处理方案五、性能优化六、使用示例完整代码七、小结一、

C#使用Spire.Doc for .NET实现HTML转Word的高效方案

《C#使用Spire.Docfor.NET实现HTML转Word的高效方案》在Web开发中,HTML内容的生成与处理是高频需求,然而,当用户需要将HTML页面或动态生成的HTML字符串转换为Wor... 目录引言一、html转Word的典型场景与挑战二、用 Spire.Doc 实现 HTML 转 Word1

使用Python实现Word文档的自动化对比方案

《使用Python实现Word文档的自动化对比方案》我们经常需要比较两个Word文档的版本差异,无论是合同修订、论文修改还是代码文档更新,人工比对不仅效率低下,还容易遗漏关键改动,下面通过一个实际案例... 目录引言一、使用python-docx库解析文档结构二、使用difflib进行差异比对三、高级对比方

Web服务器-Nginx-高并发问题

《Web服务器-Nginx-高并发问题》Nginx通过事件驱动、I/O多路复用和异步非阻塞技术高效处理高并发,结合动静分离和限流策略,提升性能与稳定性... 目录前言一、架构1. 原生多进程架构2. 事件驱动模型3. IO多路复用4. 异步非阻塞 I/O5. Nginx高并发配置实战二、动静分离1. 职责2

Python从Word文档中提取图片并生成PPT的操作代码

《Python从Word文档中提取图片并生成PPT的操作代码》在日常办公场景中,我们经常需要从Word文档中提取图片,并将这些图片整理到PowerPoint幻灯片中,手动完成这一任务既耗时又容易出错,... 目录引言背景与需求解决方案概述代码解析代码核心逻辑说明总结引言在日常办公场景中,我们经常需要从 W

Spring Security 前后端分离场景下的会话并发管理

《SpringSecurity前后端分离场景下的会话并发管理》本文介绍了在前后端分离架构下实现SpringSecurity会话并发管理的问题,传统Web开发中只需简单配置sessionManage... 目录背景分析传统 web 开发中的 sessionManagement 入口ConcurrentSess

Python多线程应用中的卡死问题优化方案指南

《Python多线程应用中的卡死问题优化方案指南》在利用Python语言开发某查询软件时,遇到了点击搜索按钮后软件卡死的问题,本文将简单分析一下出现的原因以及对应的优化方案,希望对大家有所帮助... 目录问题描述优化方案1. 网络请求优化2. 多线程架构优化3. 全局异常处理4. 配置管理优化优化效果1.

C#使用Spire.XLS快速生成多表格Excel文件

《C#使用Spire.XLS快速生成多表格Excel文件》在日常开发中,我们经常需要将业务数据导出为结构清晰的Excel文件,本文将手把手教你使用Spire.XLS这个强大的.NET组件,只需几行C#... 目录一、Spire.XLS核心优势清单1.1 性能碾压:从3秒到0.5秒的质变1.2 批量操作的优雅