首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 分布式唯一 ID 生成:時間戳 + 原子計數器實作

     編輯:Java 相關知識

需求背景

資料庫主鍵不能依賴自增 ID (分庫分表衝突、洩露業務量、單點寫入瓶頸)。常見方案:UUID (無序、長)、Snowflake (需機器號、時鐘回撥風險)。本文實作一個**單機高併發、有序、純數字**的 ID 生成器:毫秒時間戳 (13 位) + 4 位原子計數器 = 19 位 Long,支援單毫秒 10,000 次並發。

完整程式碼

import java.util.concurrent.atomic.AtomicInteger;

public class IdGenerator {
    /** 計數器:單毫秒內遞增,達 10000 歸零 */
    private static final AtomicInteger COUNTER = new AtomicInteger(0);
    private static final int MAX_COUNTER = 10000; // 4 位數上限

    /** 生成唯一 ID
     * @return 19 位 Long:時間戳(13位) + 計數器(4位補零)
     */
    public static long nextId() {
        long timestamp = System.currentTimeMillis(); // 13 位
        int count = COUNTER.getAndIncrement();
        if (count >= MAX_COUNTER) {
            // 簡單自旋等待下一毫秒 (高併發下可改用 while 循環 CAS)
            while (System.currentTimeMillis() == timestamp) {
                Thread.yield();
            }
            COUNTER.set(0);
            timestamp = System.currentTimeMillis();
            count = COUNTER.getAndIncrement();
        }
        // 組合:timestamp * 10000 + count
        return timestamp * 10000L + count;
    }

    // --- 測試主程式 ---
    public static void main(String[] args) throws InterruptedException {
        // 單執行緒測試
        for (int i = 0; i < 5; i++) System.out.println(nextId());

        // 多執行緒壓測:10 萬並發
        int threads = 10;
        int perThread = 10000;
        Thread[] ts = new Thread[threads];
        for (int i = 0; i < threads; i++) {
            ts[i] = new Thread(() -> {
                for (int j = 0; j < perThread; j++) nextId();
            });
            ts[i].start();
        }
        for (Thread t : ts) t.join();
        System.out.println("10 萬並發生成完成,最後 ID:" + nextId());
    }
}

核心邏輯解析

  1. 時間戳高位:保證宏觀遞增,利於資料庫 B+ 樹索引插入效能 (避免頁分裂)。
  2. AtomicInteger 計數器:無鎖 CAS 保證線程安全,單毫秒 10,000 上限足夠大多數業務。
  3. 計數器溢位處理:達上限自旋等待下一毫秒,避免 ID 重複。(極高併發建議改用 LongAdder 或分段鎖)。
  4. 數字拼接:timestamp * 10000 + count 比字串拼接快數數量級,且保持數值型態。

與主流方案對比

方案長度有序性單機 QPS依賴適用場景
UUID36 字元無序極高無非關鍵主鍵、離線生成
Snowflake19 位趨勢遞增409 萬/毫秒機器號、時鐘分布式系統標準選擇
本文方案19 位嚴格遞增1 萬/毫秒無單機/主從、簡易分庫分表
資料庫自增不定遞增受限單點DB單體應用

生產環境強化建議

  • ⏰ 時鐘回撥防護:記錄上次時間戳,若 timestamp < lastTimestamp 拋異常或等待。
  • 📦 批量預生成:背景執行緒預生成 ID 池,業務執行緒直接取用,進一步降低延遲。
  • 🔧 Spring 整合:封裝為 @Component,注入 Service 層使用。
  • 📊 監控指標:暴露 counter 當前值、生成耗時、等待次數到 Prometheus。

此方案零依賴、程式碼極簡、效能優異,是中小型專案從自增 ID 遷移的最佳踏腳石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved