如何设计一个能扛住双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

相关文章

无法启动此程序因为计算机丢失api-ms-win-core-path-l1-1-0.dll修复方案

《无法启动此程序因为计算机丢失api-ms-win-core-path-l1-1-0.dll修复方案》:本文主要介绍了无法启动此程序,详细内容请阅读本文,希望能对你有所帮助... 在计算机使用过程中,我们经常会遇到一些错误提示,其中之一就是"api-ms-win-core-path-l1-1-0.dll丢失

利用Python实现可回滚方案的示例代码

《利用Python实现可回滚方案的示例代码》很多项目翻车不是因为不会做,而是走错了方向却没法回头,技术选型失败的风险我们都清楚,但真正能提前规划“回滚方案”的人不多,本文从实际项目出发,教你如何用Py... 目录描述题解答案(核心思路)题解代码分析第一步:抽象缓存接口第二步:实现两个版本第三步:根据 Fea

SpringBoot实现接口数据加解密的三种实战方案

《SpringBoot实现接口数据加解密的三种实战方案》在金融支付、用户隐私信息传输等场景中,接口数据若以明文传输,极易被中间人攻击窃取,SpringBoot提供了多种优雅的加解密实现方案,本文将从原... 目录一、为什么需要接口数据加解密?二、核心加解密算法选择1. 对称加密(AES)2. 非对称加密(R

使用Python自动化生成PPT并结合LLM生成内容的代码解析

《使用Python自动化生成PPT并结合LLM生成内容的代码解析》PowerPoint是常用的文档工具,但手动设计和排版耗时耗力,本文将展示如何通过Python自动化提取PPT样式并生成新PPT,同时... 目录核心代码解析1. 提取 PPT 样式到 jsON关键步骤:代码片段:2. 应用 JSON 样式到

MySQL精准控制Binlog日志数量的三种方案

《MySQL精准控制Binlog日志数量的三种方案》作为数据库管理员,你是否经常为服务器磁盘爆满而抓狂?Binlog就像数据库的“黑匣子”,默默记录着每一次数据变动,但若放任不管,几天内这些日志文件就... 目录 一招修改配置文件:永久生效的控制术1.定位my.cnf文件2.添加核心参数不重启热更新:高手应

SpringBoot实现二维码生成的详细步骤与完整代码

《SpringBoot实现二维码生成的详细步骤与完整代码》如今,二维码的应用场景非常广泛,从支付到信息分享,二维码都扮演着重要角色,SpringBoot是一个非常流行的Java基于Spring框架的微... 目录一、环境搭建二、创建 Spring Boot 项目三、引入二维码生成依赖四、编写二维码生成代码五

MySQL中like模糊查询的优化方案

《MySQL中like模糊查询的优化方案》在MySQL中,like模糊查询是一种常用的查询方式,但在某些情况下可能会导致性能问题,本文将介绍八种优化MySQL中like模糊查询的方法,需要的朋友可以参... 目录1. 避免以通配符开头的查询2. 使用全文索引(Full-text Index)3. 使用前缀索

Python解决雅努斯问题实例方案详解

《Python解决雅努斯问题实例方案详解》:本文主要介绍Python解决雅努斯问题实例方案,雅努斯问题是指AI生成的3D对象在不同视角下出现不一致性的问题,即从不同角度看物体时,物体的形状会出现不... 目录一、雅努斯简介二、雅努斯问题三、示例代码四、解决方案五、完整解决方案一、雅努斯简介雅努斯(Janu

Linux高并发场景下的网络参数调优实战指南

《Linux高并发场景下的网络参数调优实战指南》在高并发网络服务场景中,Linux内核的默认网络参数往往无法满足需求,导致性能瓶颈、连接超时甚至服务崩溃,本文基于真实案例分析,从参数解读、问题诊断到优... 目录一、问题背景:当并发连接遇上性能瓶颈1.1 案例环境1.2 初始参数分析二、深度诊断:连接状态与

Android与iOS设备MAC地址生成原理及Java实现详解

《Android与iOS设备MAC地址生成原理及Java实现详解》在无线网络通信中,MAC(MediaAccessControl)地址是设备的唯一网络标识符,本文主要介绍了Android与iOS设备M... 目录引言1. MAC地址基础1.1 MAC地址的组成1.2 MAC地址的分类2. android与I