用戶註冊時分配 ID,不希望通過連續 ID 推測總用戶數或他人 ID。需生成看似無規律、實則無重複的自然數序列。
f(k) = (k * F(N-1)) mod F(N)
F(0)=0, F(1)=1, F(N+2)=F(N+1)+F(N)
缺點:非隨機,序列可預測。
X_{n+1} = (a * X_n + c) mod m
a、c、m 通常取質數java.util.Random、Borland C 均用此法m,參數選擇不當會縮短周期核心思想:線性函數對質數取模保證一一映射。
F(N) = (seed * (N + seed)) mod prime
N:遞增序列號(1,2,3...)seed:隨機種子(啟動時生成,持久化存儲)prime:大於預期最大 ID 的質數(如 2147483647)seed*(N+seed) 在模 prime 意義下單調遞增且無重複,輸出序列無重覆seed 即可生成完全不同的序列順序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 -- 最後使用的序列號
);
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;
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 ;
prime 範圍內無重複seed、prime、last_n 三個數值N 可作為審計追蹤依據seed 即可生成新序列,舊序列不可逆推prime 必須 > 業務預估最大 ID 數量,建議用已知大質數(如 2^31-1)UPDATE ... last_n = last_n + 1 需行級鎖,MySQL InnoDB 自動處理