為什么不推薦使用數據庫自增主鍵?
分庫分表問題:
- 自增ID在分庫分表場景下會導致ID沖突
- 需要額外機制(如步長設置)來保證全局唯一,增加系統復雜度
安全性問題:
- 自增ID容易暴露業務量(如訂單號連續)
- 可能被惡意爬取數據
分布式系統限制:
- 依賴數據庫實現,在分布式系統中可能成為性能瓶頸
- 高并發場景下獲取ID可能產生競爭
數據遷移困難:
- 不同數據庫的自增機制可能不兼容
- 合并數據時容易產生沖突
為什么不推薦使用UUID作為主鍵?
存儲空間大:
- UUID通常需要32個字符(16字節),比長整型(8字節)占用更多空間
- 導致索引占用更多內存,降低查詢性能
無序性問題:
- UUID是無序的,導致B+樹索引頻繁分裂
- 插入性能下降,產生更多磁盤碎片
可讀性差:
- 對人類不友好,難以記憶和識別
索引效率低:
- 較大的鍵值導致索引層級增加
- 范圍查詢效率降低
雪花算法(Snowflake)存在的問題
時鐘回撥問題:
- 依賴系統時鐘,時鐘回撥會導致ID重復
- 需要額外處理邏輯,增加系統復雜度
分布式環境配置:
- 需要確保workerId在集群中唯一
- 動態擴容時workerId分配可能成為問題
ID長度限制:
- 標準的64位雪花ID可能在某些場景下不夠用
- 擴展位數會影響兼容性
時間戳依賴:
- 如果系統運行時間超過69年(時間戳部分耗盡),需要特殊處理
數據傾斜問題:
- 短時間內大量生成ID可能導致數據熱點
主鍵選擇建議
單機系統:
- 可以考慮自增主鍵,簡單高效
分布式系統:
- 推薦使用改進版的雪花算法(如美團的Leaf、百度的UidGenerator)
- 也可以考慮Redis生成ID或數據庫號段模式
- 將序列號進行修改防止數據傾斜(如將時間戳最后一位賦值給序列號最后一位);
?特殊需求場景:
- 需要隱藏業務信息的可以使用哈希ID
- 需要可讀性的可以使用業務編號+隨機數組合
NoSQL系統:
- 可以充分利用各數據庫特有的ID生成機制
- 如MongoDB的ObjectId
每種方案都有其適用場景,應根據具體業務需求、數據規模和系統架構來選擇最合適的主鍵策略。