作者: vivo 互聯網服務器團隊- Zhang Jing
本文以遊戲週週樂的幸運碼為切入點,針對其生成過程中涉及的隨機性、唯一性及高併發等特點,設計了一種基於號段+子碼的創新架構。該方案不僅在生成速度上表現突出,還顯著提升了存儲效率,同時降低了擴容成本,為類似的號碼生成系統提供了設計上的新思路和啓發。
文章太長?1分鐘看圖抓住核心觀點👇
一、業務背景
用户可通過完成相關任務獲取週週樂幸運碼,幸運碼的投放規則如下:
- 基礎投放量:每期100萬注唯一無重複的6位數字幸運碼
- 動態擴容機制:參與人數超額時,可實時追加100萬注
二、幸運碼特性
根據背景介紹,我們可以知道幸運碼需要支持如下特性:
- 隨機性,發給每個用户的幸運碼都是隨機的,同時每個用户領取的多個幸運碼也是隨機的。
- 唯一性,每一組的幸運碼中,各幸運碼都是唯一的。
- 範圍性,幸運碼嚴格限定在000000到999999區間內。
- 高併發,幸運碼的生成和發放需要支持高併發,能夠至少達到300QPS。
- 可追加,在當期活動非常火爆時,需要可臨時追加一組幸運碼庫存。
三、方案選型
鑑於幸運碼需嚴格限定在6位數字範圍內(000000-999999),傳統雪花算法因生成超長ID(64位二進制)且依賴時間戳遞增特性,難以直接適配。以下將對比三種方案:實時隨機生成模式、預生成庫存模式及號段+子碼模式,並會根據生成速度、存儲效率、擴容成本三個核心指標進行系統性評估,最終選擇出最優解決方案。
3.1 方案一:實時隨機生成模式
實現邏輯:
- 生成隨機數
- 再查詢數據庫是否有該隨機數
- 若沒有則入庫,完成幸運碼發放
- 若有再重新執行第一步
缺陷分析:
- 碰撞概率隨庫存消耗不斷上升
- 數據庫IO壓力隨併發量線性增長
- 不滿足高併發場景性能要求
3.2 方案二:預生成庫存模式
實現邏輯:
採用預生成幸運碼方式:離線生成100萬個幸運碼,隨機打散,寫入數據庫,每個幸運碼對應一個從1自增的序列號,並使用Redis記錄幸運碼序列號索引,初始值為1。
發放步驟如下:
- 從Redis查詢幸運碼序列號索引
- 使用該索引查詢幸運碼,並完成幸運碼發放
- 遞增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 幸運碼發放
發放步驟:
- 隨機獲取至多15個可用號段
- 遍歷號段
- 搶佔號段的分佈式鎖
- 若號段的分佈式鎖搶佔成功,則隨機獲取號段中可用的子碼,再根據號段和子碼生成幸運碼
- 若號段的分佈式鎖搶佔失敗,則遍歷下一個號段,並重覆上述步驟
五、總結
(1)雙重隨機保障
- 一級隨機:號段選擇隨機(0-999)
- 二級隨機:子碼選擇隨機(0-999)
- 通過號段隨機和子碼隨機方式確保生成的幸運碼完全隨機
(2)數據唯一性
- 通過號段唯一和號段內的子碼唯一確保生成的幸運碼全局唯一
(3)彈性擴展能力
- 擴容耗時僅需秒級別
- 存儲空間相比預生成方案節省80%
(4)高性能發放
- 通過多重緩存及高效號段搶佔策略大幅提升幸運碼生成效率
- 實測QPS>300,平均響應時間<15ms
本設計方案通過創新的號段+子碼管理機制,在保證號碼隨機性和唯一性的同時,實現了高併發場景下的穩定服務能力,為類似號碼生成系統的設計提供了可複用的架構範式。