首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

生成不重複隨機 ID 序列算法:從線性同餘到基於種子的無重複序列

     編輯:MySQL 資料庫相關知識

業務場景

用戶註冊時分配 ID,不希望通過連續 ID 推測總用戶數或他人 ID。需生成看似無規律、實則無重複的自然數序列。

算法演進

1. 斐波那契取模(不可用)

f(k) = (k * F(N-1)) mod F(N)
F(0)=0, F(1)=1, F(N+2)=F(N+1)+F(N)

缺點:非隨機,序列可預測。

2. 線性同餘生成器 (LCG) - 經典偽隨機

X_{n+1} = (a * X_n + c) mod m
  • a、c、m 通常取質數
  • Java java.util.Random、Borland C 均用此法
  • 周期最長為 m,參數選擇不當會縮短周期
  • 需 64 位整數支持大模數(如 2^48)

3. 改進:基於序列號的無重複映射

核心思想:線性函數對質數取模保證一一映射。

F(N) = (seed * (N + seed)) mod prime
  • N:遞增序列號(1,2,3...)
  • seed:隨機種子(啟動時生成,持久化存儲)
  • prime:大於預期最大 ID 的質數(如 2147483647)
  • 因 seed*(N+seed) 在模 prime 意義下單調遞增且無重複,輸出序列無重覆
  • 改變 seed 即可生成完全不同的序列順序

數據庫實現方案 (Oracle/PostgreSQL/MySQL)

序列控制表

CREATE TABLE seq_control (
    seq_id       VARCHAR(50) PRIMARY KEY,  -- 業務標識
    seed         BIGINT NOT NULL,          -- 隨機種子
    prime_val    BIGINT NOT NULL,          -- 質數模數
    last_n       BIGINT NOT NULL DEFAULT 0 -- 最後使用的序列號
);

獲取下一個 ID (Oracle PL/SQL 示例)

CREATE OR REPLACE FUNCTION next_random_id(p_seq_id VARCHAR2)
RETURN NUMBER IS
    v_seed    NUMBER;
    v_prime   NUMBER;
    v_n       NUMBER;
    v_id      NUMBER;
BEGIN
    -- 1. 獲取並更新序列號
    UPDATE seq_control
    SET last_n = last_n + 1
    WHERE seq_id = p_seq_id
    RETURNING seed, prime_val, last_n INTO v_seed, v_prime, v_n;

    -- 2. 計算隨機 ID
    v_id := MOD(v_seed * (v_n + v_seed), v_prime);
    RETURN v_id;
END;

MySQL 存儲過程實現

DELIMITER //
CREATE PROCEDURE GetNextRandomId(IN p_seq_id VARCHAR(50), OUT p_id BIGINT)
BEGIN
    DECLARE v_seed, v_prime, v_n BIGINT;
    UPDATE seq_control
    SET last_n = last_n + 1
    WHERE seq_id = p_seq_id;
    SELECT seed, prime_val, last_n INTO v_seed, v_prime, v_n
    FROM seq_control WHERE seq_id = p_seq_id;
    SET p_id = MOD(v_seed * (v_n + v_seed), v_prime);
END//
DELIMITER ;

關鍵優勢

  1. 零衝突:數學保證在 prime 範圍內無重複
  2. 無狀態計算:僅需存儲 seed、prime、last_n 三個數值
  3. 可審計:序列號 N 可作為審計追蹤依據
  4. 可重置:更換 seed 即可生成新序列,舊序列不可逆推

注意事項

  • prime 必須 > 業務預估最大 ID 數量,建議用已知大質數(如 2^31-1)
  • 高併發下 UPDATE ... last_n = last_n + 1 需行級鎖,MySQL InnoDB 自動處理
  • 若需跨數據庫節點生成,引入節點標識位(如高 16 位作節點 ID)
  • 安全性要求極高場景請使用密碼學安全隨機數生成器 (CSPRNG)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved