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

Java 產生唯一流水號/訂單號演算法實作(含日期重置與資料庫同步)

     編輯:Java 相關知識

展示一個執行緒安全的流水號產生器 SerialNum,格式為 CB + yyyyMMdd + 三位流水碼(如 CB20240520001),支援跨日歸零、重啟後透過資料庫最大值同步避免重複。

核心實作

import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.lang3.StringUtils;

public class SerialNum {
    private static String count = "000";      // 當日流水碼
    private static String dateValue = "20131115"; // 最後產生日期

    /** 產生下一筆流水號 */
    public synchronized static String getMoveOrderNo() {
        long nowNum = Long.parseLong(new SimpleDateFormat("yyyyMMdd").format(new Date()));
        if (nowNum != Long.parseLong(dateValue)) { // 跨日歸零
            count = "000";
            dateValue = String.valueOf(nowNum);
        }
        String serial = "CB" + dateValue + nextCount(count);
        return serial;
    }

    /** 從資料庫最大值同步(重啟/遷移時呼叫) */
    public synchronized static String getMoveOrderNo(String lastSerialFromDB) {
        if (lastSerialFromDB == null || lastSerialFromDB.length() < 12) return getMoveOrderNo();
        String dbDate = StringUtils.substring(lastSerialFromDB, 2, 10); // yyyyMMdd
        String dbCount = StringUtils.substring(lastSerialFromDB, 10);   // 流水碼
        if (Integer.parseInt(dbCount) > Integer.parseInt(count)) {
            dateValue = dbDate;
            count = dbCount;
        }
        return getMoveOrderNo();
    }

    private static String nextCount(String curr) {
        int next = Integer.parseInt(curr) + 1;
        String rs = String.valueOf(next);
        while (rs.length() < 3) rs = "0" + rs; // 左補零至 3 位
        count = rs;
        return rs;
    }

    // 測試
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) System.out.println(getMoveOrderNo());
    }
}

執行結果範例

CB20240520001
CB20240520002
...
CB20240520010

關鍵設計分析

生產環境強化建議

  1. 分散式環境:改用資料庫序列 (Oracle Sequence, MySQL AUTO_INCREMENT, PostgreSQL SEQUENCE) 或 Redis INCR + Lua 腳本保證原子性。
  2. 高併發:AtomicInteger + LongAdder 取代 synchronized;或採用 Snowflake 演算法 (64-bit: timestamp + workerId + sequence)。
  3. 格式擴充:加入業務類型前綴 (SO/PO/RO)、機房代碼、隨機因子等。
  4. 持久化策略:定期將 count 寫入 Redis/DB,重啟時快速恢復,避免全表掃描 MAX()。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
特性實作方式備註
執行緒安全方法加 synchronized單機單 JVM 環境足夠;分叢集需分散式鎖或 DB 序列
日期歸零比對 yyyyMMdd 整數跨日自動重置 count
持久化同步getMoveOrderNo(lastSerial)啟動時查詢 DB MAX(serial) 傳入,確保不重複
格式固定長CB + 8 碼日期 + 3 碼流水共 13 碼,利於資料庫索引與排序