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

PHP 生成唯一訂單號的三種高效策略

     編輯:PHP 綜合知識

核心需求

訂單號需唯一、可追溯、長度適中、無規律可循(防刷單)。常見組成要素:時間、隨機數、業務前綴、校驗碼。

策略一:字母年份 + 十六進制月份 + 日 + 時間戳尾碼 + 微秒 + 隨機數(16 位)

$yCode = ['A','B','C','D','E','F','G','H','I','J']; // 對應 2011-2020
$orderSn = $yCode[intval(date('Y')) - 2011]
         . strtoupper(dechex(date('m')))   // 月份轉大寫十六進制
         . date('d')                       // 日期
         . substr(time(), -5)              // 時間戳後 5 碼
         . substr(microtime(), 2, 5)       // 微秒部分
         . sprintf('%02d', rand(0, 99));   // 兩位隨機數
// 輸出範例:A422694333616096

特點:含業務語義(年月日)、高並發下極低衝突率。

策略二:日期 + uniqid() 截取 ASCII 碼組合(16 位)

function build_order_no() {
    return date('Ymd')
         . substr(
               implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))),
               0, 8
           );
}
echo build_order_no();
// 輸出範例:2014062356100485

原理:uniqid() 基於微秒時間,取後段字符轉 ASCII 碼再截取,變異度高。

策略三:更通用的高併發安全生成器(推薦)

function generateOrderNo(string $prefix = 'ORD'): string {
    // 1. 日期時間(精確到毫秒)
    $time = explode(' ', microtime());
    $ms = sprintf('%03d', (int)($time[0] * 1000));
    $date = date('YmdHis') . $ms; // 17 碼

    // 2. 進程/執行緒 ID(PHP-FPM 可用 getmypid())
    $pid = sprintf('%05d', getmypid() % 100000);

    // 3. 遞增序號(Redis 原子計數或檔案鎖)
    static $seq = 0;
    $seq = ($seq + 1) % 10000;
    $seqStr = sprintf('%04d', $seq);

    // 4. 組合:前綴(3) + 時間(17) + PID(5) + 序號(4) = 29 碼
    return $prefix . $date . $pid . $seqStr;
}

// 使用範例
echo generateOrderNo('ORD'); // ORD2024011512304512300001234

優點:

  • 全域唯一(時間 + 進程 + 序號)。
  • 可按前綴區分業務(ORD/PAY/REF)。
  • 長度固定,利於資料庫索引與日誌分析。

避坑指南

  1. 不要只用 time() + rand(),高併發極易重複。
  2. 避免使用資料庫自增 ID 作為訂單號(洩露營運數據)。
  3. 分布式系統建議引入 Snowflake 演算法或 Redis 原子計數器。
  4. 訂單號欄位建立唯一索引,捕獲 Duplicate entry 異常重試。

結語

根據業務規模選擇適合策略:中小專案策略一/二足矣;高併發電商建議策略三或引入分布式 ID 生成服務。

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