号码生成系统的创新实践:游戏周周乐幸运码设计

作者: vivo 互联网服务器团队- Zhang Jing

本文以游戏周周乐的幸运码为切入点,针对其生成过程中涉及的随机性、唯一性及高并发等特点,设计了一种基于号段+子码的创新架构。该方案不仅在生成速度上表现突出,还显著提升了存储效率,同时降低了扩容成本,为类似的号码生成系统提供了设计上的新思路和启发。

文章太长?1分钟看图抓住核心观点👇

一、业务背景

用户可通过完成相关任务获取周周乐幸运码,幸运码的投放规则如下:

  • 基础投放量:每期100万注唯一无重复的6位数字幸运码

  • 动态扩容机制:参与人数超额时,可实时追加100万注

二、幸运码特性

根据背景介绍,我们可以知道幸运码需要支持如下特性:

  • 随机性,发给每个用户的幸运码都是随机的,同时每个用户领取的多个幸运码也是随机的。

  • 唯一性,每一组的幸运码中,各幸运码都是唯一的。

  • 范围性,幸运码严格限定在000000到999999区间内。

  • 高并发,幸运码的生成和发放需要支持高并发,能够至少达到300QPS。

  • 可追加,在当期活动非常火爆时,需要可临时追加一组幸运码库存。

三、方案选型

鉴于幸运码需严格限定在6位数字范围内(000000-999999),传统雪花算法因生成超长ID(64位二进制)且依赖时间戳递增特性,难以直接适配。以下将对比三种方案:实时随机生成模式、预生成库存模式及号段+子码模式,并会根据生成速度、存储效率、扩容成本三个核心指标进行系统性评估,最终选择出最优解决方案。

3.1 方案一:实时随机生成模式

实现逻辑:

  1. 生成随机数

  2. 再查询数据库是否有该随机数

  3. 若没有则入库,完成幸运码发放

  4. 若有再重新执行第一步

缺陷分析:

  • 碰撞概率随库存消耗不断上升

  • 数据库IO压力随并发量线性增长

  • 不满足高并发场景性能要求

3.2 方案二:预生成库存模式

实现逻辑:

采用预生成幸运码方式:离线生成100万个幸运码,随机打散,写入数据库,每个幸运码对应一个从1自增的序列号,并使用Redis记录幸运码序列号索引,初始值为1。

发放步骤如下:

  1. 从Redis查询幸运码序列号索引

  2. 使用该索引查询幸运码,并完成幸运码发放

  3. 递增Redis的序列号索引,确保序列号索引关联的幸运码是下一个可发放的幸运码

缺陷分析:

  • 存储空间浪费:未发放号码占用存储

  • 扩容效率低下:追加库存需重新预生成

3.3 方案三:号段+子码模式

采用号段+子码机制:

  • 号段管理:将10^6号码划分为1000个号段(号段值:0-999)

  • 子码管理:每个号段维护1000个可用子码(子码值:0-999)

  • 生成规则:幸运码=随机号段*1000+随机子码(示例:129358=129*1000+358)

3.4 方案对比

综上,我们综合幸运码生成速度、存储效率、扩容成本等指标,最终采用了号段+子码模式来生成幸运码。

四、关键技术实现

4.1 号段分层机制

将100万注幸运码划分为1000个号段(每段1000注),每个号段由两部分组成:

  • 号段ID:号段ID为唯一且不重复的整数,范围介于0到999之间。

  • 子码串:1000位字符串,采用"01"标记使用状态,0表示未使用,1表示已使用,初始全0。

幸运码生成公式:

幸运码 = 号段ID * 1000 + 子码位置

该设计既保留了生成幸运码的随机性(号段ID随机+子码随机),又通过子码的类比特位存储方式提升了存储效率。

4.2 分布式并发控制

4.2.1 多级缓存策略

Redis存储可用号段集合,若号段的子码使用完,该号段会从Redis集合中剔除,同时本地缓存也会预加载可用号段,确保发码时能更高效地获取候选号段。

4.2.2 高效锁抢占策略

系统为每个号段分配了分布式锁,当执行发放幸运码时,会从本地缓存随机获取15个候选号段。然后在遍历获取号段时,将等待锁的超时时间设置成30ms,确保号段被占用的情况下能够快速遍历到下一个号段(根据实际场景统计,等待锁的情况很少发生,一般最多遍历到第二个号段即可成功抢占)。一旦成功获得号段的分布式锁后,便可进一步随机获取该号段下的可用子码。

4.2.3 动态库存策略

要追加库存,只需再创建一组幸运码号段,并写入Redis,后续发放时获取该组的可用号段生成幸运码即可。从性能和存储空间上远优于预生成方式。

4.3 幸运码发放

发放步骤

  1. 随机获取至多15个可用号段

  2. 遍历号段

  3. 抢占号段的分布式锁

  4. 若号段的分布式锁抢占成功,则随机获取号段中可用的子码,再根据号段和子码生成幸运码

  5. 若号段的分布式锁抢占失败,则遍历下一个号段,并重复上述步骤

五、总结

(1)双重随机保障

  • 一级随机:号段选择随机(0-999)

  • 二级随机:子码选择随机(0-999)

  • 通过号段随机和子码随机方式确保生成的幸运码完全随机

(2)数据唯一性

  • 通过号段唯一和号段内的子码唯一确保生成的幸运码全局唯一

(3)弹性扩展能力

  • 扩容耗时仅需秒级别

  • 存储空间相比预生成方案节省80%

(4)高性能发放

  • 通过多重缓存及高效号段抢占策略大幅提升幸运码生成效率

  • 实测QPS>300,平均响应时间<15ms

本设计方案通过创新的号段+子码管理机制,在保证号码随机性和唯一性的同时,实现了高并发场景下的稳定服务能力,为类似号码生成系统的设计提供了可复用的架构范式。

相关推荐
uzong4 小时前
技术故障复盘模版
后端
GetcharZp4 小时前
基于 Dify + 通义千问的多模态大模型 搭建发票识别 Agent
后端·llm·agent
桦说编程5 小时前
Java 中如何创建不可变类型
java·后端·函数式编程
IT毕设实战小研5 小时前
基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
java·开发语言·spring boot·后端·spring·毕业设计·课程设计
wyiyiyi5 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
阿华的代码王国6 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
Jimmy6 小时前
AI 代理是什么,其有助于我们实现更智能编程
前端·后端·ai编程
鼠鼠我捏,要死了捏7 小时前
生产环境Redis缓存穿透与雪崩防护性能优化实战指南
redis·cache
喂完待续7 小时前
Apache Hudi:数据湖的实时革命
大数据·数据仓库·分布式·架构·apache·数据库架构
AntBlack7 小时前
不当韭菜V1.1 :增强能力 ,辅助构建自己的交易规则
后端·python·pyqt