mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4mobile wallpaper 5mobile wallpaper 6mobile wallpaper 7mobile wallpaper 8mobile wallpaper 9mobile wallpaper 10mobile wallpaper 11mobile wallpaper 12
1045 字
3 分钟
破局双维度查询难题:淘宝订单ID的用户基因设计奥秘
2025-08-23

目录

一、ID结构

二、业务需求

三、具体实现


一、ID结构#

淘宝订单ID(例如:266807390250123456)包含三个核心部分:

  1. **时间序列部分 (26680739025):**标识订单生成的时间序列。
  2. **订单类型标识 (0):**用于区分不同类型的订单。
  3. **用户基因段 (123456):**嵌入的用户标识信息(用户ID的后6位)。

二、业务需求#

淘宝的核心特性就是在订单号的后6位嵌入了用户基因,那么为什么需要这么做呢?

这是为了双维度查询难题:

传统方案的痛点:

  • **userId分片:**虽然用户查询自己的订单效率极高,但噩梦在于按 orderId 查询,因为 orderId 本身不含路由信息,必须扫描所有分片,在数千分片下性能灾难。
  • **orderId分片:**按orderId查询高效,但用户查自己订单又变成全分片扫描。

或许可以完全把当前订单表复制一遍改为冗余订单id分片表,但这样一来成本翻倍不说,每次下单需强事务保证写入两个库,高并发下成为瓶颈,还增加了维护的复杂度。

所以淘宝就通过将用户id的后6位作为基因段嵌入订单id里,以这个基因段为分片键,通过查询用户全部订单时就取userId后6为转化为基因进行路由;查询单个订单就订单号后六位基因段进行路由即可。

这种方法巧妙地将用户标识融入订单ID本身,使得无论是基于userId的批量查询,还是基于orderId的单点查询,都能高效地定位到目标分片,避免了全表扫描。同时,无需维护额外的冗余。

其实淘宝订单号整个可以视作snowflake算法生成ID的一个变种,引入用户基因将机器ID位的作用大幅度弱化,因为同一毫秒内用户生成多个订单的可能性几乎为0,就算有也可以通过序列号位进行区分。省去了传统的麻烦的机器ID分配流程。

所以淘宝订单号就是用用户基因取代了机器ID位,然后将序列号位前移,再引入了订单型标识结合而成的。

三、具体实现#

核心在于从用户基因提取用户id以及将用户id转化为用户基因的两个方法。

这里我们不对这两个方法做详解,仅讲解基本流程:

public class TaobaoOrderIdGenerator {
// 基因位数
private static final int GENE_BITS = 6;
// 最大重试次数
private static final int MAX_RETRIES = 5;
// 布隆过滤器
private final RBloomFilter<String> geneBloomFilter;
public String generate(long userId) {
int retries = 0;
String orderId = null;
long userGene = 0;
// 使用随机盐值增强安全性
long salt = ThreadLocalRandom.current().nextLong();
while (orderId == null && retries < MAX_RETRIES) {
// 提取用户基因
userGene = extractGene(userId, salt);
// 布隆过滤器快速冲突预检
if (isGeneConflict(userGene)) {
// 改变盐值扰动哈希结果,尝试生成新基因
salt = mutateSalt(salt);
retries++;
// 重试
continue;
}
// 生成唯一ID
long uniquePart = generateSnowflakeId(userGene);
// 组合最终订单号
orderId = formatOrderId(uniquePart, userGene);
}
if (orderId == null) {
throw new IllegalStateException("订单号生成失败,重试次数耗尽");
}
// 将成功生成的基因添加到布隆过滤器
geneBloomFilter.add(String.valueOf(userGene));
// 存储到映射表中,redis/DB
storeGeneUserIdMapping(userGene, userId);
return orderId;
}
}

由于不能直接将用户id暴露给外界,所以可以采用哈希 + 盐值来生成基因段,但是考虑到哈希碰撞的可能性,我们可以对使用的哈希函数进行优化,将碰撞的可能性降低,同时引入布隆过滤器进行筛选拦截。

关于snowflake算法的生成可以阅读下面这篇博客: 从业务场景到知名企业开源框架全面解析分布式ID生成方案-CSDN博客https://blog.csdn.net/2401_88959292/article/details/150607790?spm=1001.2014.3001.5501

因为用户基因段是userId的单向哈希加盐,无法通过计算反向得到userId。当需要根据orderId查询订单详情时,系统需要知道这个订单属于哪个userId。

所以对于用户基因提取用户id的方法我们一般会使用映射表,在生成订单号成功后将用户基因以及其对应的用户id存储到或者DB中,提取用户id时就直接拿用户基因查询即可。


码文不易、留个赞再走吧


原文链接: 破局双维度查询难题:淘宝订单ID的用户基因设计奥秘 作者: Yilena

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

破局双维度查询难题:淘宝订单ID的用户基因设计奥秘
https://blog.csdn.net/2401_88959292/article/details/150638150?spm=1001.2014.3001.5501
作者
Yilena
发布于
2025-08-23
许可协议
CC BY 4.0

部分信息可能已经过时

相关文章 智能推荐
1
从业务场景到知名企业开源框架全面解析分布式ID生成方案
业务拆解 本文全面解析了分布式系统中的ID生成方案。首先明确了ID需具备生成不规则性、全局唯一性和单表递增性三大核心要求。接着对比了UUID、DB自增、号段模式、Snowflake雪花算法及Redis生成等基础方案的优缺点。随后,深入剖析了美团Leaf(涵盖Segment双Buffer优化与Snowflake时钟回拨处理)、百度UidGenerator(引入双环形缓冲区与时间基点提升吞吐量)以及滴滴Tinyid(优化DB号段模式并嵌入本地双Buffer)等企业级开源框架的设计思想与实现细节,为不同业务场景下的技术选型提供了详实的参考依据。
2
基于MySQL + Redis + JWT的双令牌认证方案的实现
业务拆解 本文针对单令牌认证机制存在的安全隐患与用户体验痛点,设计并实现了一套基于MySQL、Redis与JWT的双令牌(访问令牌+刷新令牌)认证方案。文章详细分析了双令牌机制的优势,通过分离认证与状态维护职责,结合Redis黑名单与分布式锁限流,有效提升了系统安全性。同时,提供了完整的Java代码实现,包括JWT工具类、Redis令牌管理服务、全局过滤器及业务层Controller逻辑,展示了如何优雅地处理令牌刷新、单点互斥登录及异常响应,为构建安全可靠的Web应用认证体系提供了实践参考。
3
点餐场景下:分析实现十万级用户日志的店铺推荐方案
业务拆解 本文针对点餐小程序十万级用户进店日志场景,设计并实现了一套高效的个性化店铺推荐方案。通过冷热数据分离策略,利用Elasticsearch存储近30天热数据,结合MySQL与Redis优化查询性能。文章详细阐述了基于访问频次、分区及分类偏好的加权评分排序算法,并规划了每日定时执行的离线分析任务以平衡系统开销。最后,提供了完整的实体类定义、ES数据迁移定时任务及多线程并发日志分析的Java代码实现,为海量日志分析与推荐系统落地提供了实践参考。
4
优先队列流式处理 + 多路归并排序:轻松实现DB分表严格有序的分页查询
业务拆解 本文针对在MySQL分表架构下且磁盘空间紧张的场景,提出了一种高效实现严格有序分页查询的解决方案。面对跨表查询带来的深分页难题,文章摒弃了建立庞大映射表的空间换时间策略,转而采用“优先队列流式处理 + 多路归并排序”的创新方法。通过虚拟线程并行游标查询各分表数据,并利用容量固定的优先队列在内存中实时维护Top-N结果,有效控制了内存占用并避免了OOM风险。文章详细解析了方案的设计思路,并提供了完整的Java代码实现,经测试在万级分表数据下响应时间可达毫秒级。
5
如何应对海量Key带来的redis内存占用问题?
业务拆解 本文针对海量Key导致的Redis内存占用过高问题,深入分析了内存碎片化与元数据开销的根源,并提出了五种切实可行的解决方案。从基础的合并小Key(利用Hash结构)与临时添加TTL救急,到架构层面的Redis集群模式与Redis on Flash(内存+SSD)降本方案,再到结合MySQL的冷热数据分离策略(全量/冷数据存DB,热数据存Redis)。文章通过详实的流程图与优劣对比,帮助开发者在不同预算与业务场景下,科学应对Redis内存瓶颈。

目录

封面
Sample Song
Sample Artist
封面
Sample Song
Sample Artist
0:00 / 0:00