用雪花 id 和 uuid 做 MySQL 主鍵,被領(lǐng)導(dǎo)懟了
兄弟們,上周三下午,我正對著電腦美滋滋地敲代碼,突然背后傳來一聲 “你這主鍵用的啥?”—— 回頭一看,領(lǐng)導(dǎo)正皺著眉盯著我屏幕上的 MySQL 表結(jié)構(gòu)。我挺得意地說 “用的雪花 ID 啊,分布式環(huán)境下唯一,多高級”,結(jié)果領(lǐng)導(dǎo)當(dāng)場就懟了我一句:“高級?你知道這玩意兒給 MySQL 挖坑有多深嗎?”
當(dāng)時我臉一下子就紅了,心里還嘀咕 “不就是個主鍵嗎,能有啥大問題”,但后來跟著領(lǐng)導(dǎo)扒了半天原理,又自己做了測試,才發(fā)現(xiàn)原來選主鍵這事兒,真不是 “能生成唯一 ID 就行” 這么簡單。今天就把我踩過的坑、搞懂的門道都跟大家掰扯掰扯,省得你們跟我一樣,被領(lǐng)導(dǎo)懟了還不知道為啥。
先搞明白:MySQL 主鍵到底要的是啥?
在說雪花 ID 和 UUID 之前,咱得先統(tǒng)一個認(rèn)知 ——MySQL(尤其是咱們常用的 InnoDB 引擎)對主鍵的要求,跟找對象似的,得 “門當(dāng)戶對” 才行。你不能光看 “唯一” 這一個優(yōu)點(diǎn),就不管其他條件了,不然早晚得出問題。
InnoDB 這引擎有個很關(guān)鍵的特性叫 “聚簇索引”,簡單說就是 “主鍵索引和數(shù)據(jù)行綁在一塊兒”。你可以把它理解成一本書,主鍵索引就是目錄,數(shù)據(jù)行就是正文內(nèi)容,目錄的順序和正文的順序是完全對應(yīng)的。要是目錄亂序,你找內(nèi)容的時候就得翻來翻去;要是目錄順序整齊,一下就能定位到地方。
所以 MySQL 主鍵的核心要求就三個,少一個都不行:
1. 唯一性:這是底線,沒商量
不管是自增 ID、雪花 ID 還是 UUID,首先得保證 “不重復(fù)”。你總不能讓兩個數(shù)據(jù)共用一個主鍵吧?就像每個人的身份證號不能一樣,不然銀行取錢都能取錯,這是最基本的要求,沒啥好說的。
2. 有序性:這是性能的關(guān)鍵,很多人都忽略
剛才說的聚簇索引,要是主鍵是有序的,比如自增 ID 1、2、3、4……InnoDB 插入數(shù)據(jù)的時候,就知道直接往最后面加就行,跟排隊(duì)似的,順著來,效率特別高。
但要是主鍵是無序的,比如 UUID 那種長得亂七八糟的字符串,插入的時候就麻煩了 ——InnoDB 得先找這個 ID 該插在哪個位置,可能插在中間某個地方,這時候就需要 “頁分裂”。啥是頁分裂?你可以想象成書架上的書排滿了,你要把一本新書插進(jìn)中間,就得先把后面的書都往后挪一挪,騰出地方。數(shù)據(jù)量小的時候還好,數(shù)據(jù)量大了,這挪來挪去的功夫可就多了,插入速度會越來越慢,索引還會變得特別臃腫。
3. 占用空間?。涸叫≡胶?,別給數(shù)據(jù)庫添負(fù)擔(dān)
主鍵是要存在索引里的,而且二級索引(比如你建的 name 索引、age 索引)里存的也是主鍵的值。要是主鍵占用空間大,比如 UUID 是 36 個字符,那索引文件就會變得特別大,不僅占磁盤空間,還會影響查詢速度 —— 因?yàn)閮?nèi)存里能裝下的索引數(shù)據(jù)少了,得頻繁去磁盤讀數(shù)據(jù),速度能不慢嗎?
搞懂這三個要求,咱們再回頭看雪花 ID 和 UUID,為啥用它們做 MySQL 主鍵會被領(lǐng)導(dǎo)懟,就一目了然了。
先扒 UUID:看著萬能,實(shí)則是 MySQL 的 “空間刺客”
咱們先說說 UUID,這玩意兒全稱是 “通用唯一識別碼”,格式大概是這樣的:550e8400-e29b-41d4-a716-446655440000,一共 36 個字符,看著挺唬人,而且確實(shí)能保證全球唯一,不管你多少臺機(jī)器生成,都不會重復(fù)。
很多剛接觸分布式的同學(xué),一聽說要保證 ID 唯一,第一個想到的就是 UUID,覺得 “這玩意兒不用配置,拿來就用,多方便”。但你要是把它當(dāng) MySQL 主鍵,麻煩就來了。
問題 1:無序性直接觸發(fā) “頁分裂地獄”
UUID 最大的問題就是 “無序”—— 你生成的兩個 UUID,誰大誰小完全沒規(guī)律。比如你剛插入一個550e8400開頭的,下一個可能是a7164466開頭的,再下一個又可能是12345678開頭的。
這對 InnoDB 的聚簇索引來說,簡直是災(zāi)難。我之前做過一個測試:用 UUID 當(dāng)主鍵,往 MySQL 里插入 100 萬條數(shù)據(jù),前 10 萬條的時候還挺順暢,插入速度大概每秒 1 萬條;但到了 50 萬條之后,速度就掉到每秒 3000 條了;到 100 萬條的時候,每秒只能插 1000 多條,而且磁盤 IO 占用率直接飆到 90% 以上。
后來我用工具查了一下索引情況,發(fā)現(xiàn)索引的 “碎片率” 高達(dá) 60%—— 這就是頁分裂搞的鬼。因?yàn)槊看尾迦攵家矓?shù)據(jù),索引里全是碎片,就像你衣柜里的衣服亂堆一樣,找的時候特別費(fèi)勁。
反觀用自增 ID 做主鍵,插入 100 萬條數(shù)據(jù),速度一直穩(wěn)定在每秒 1.5 萬條左右,索引碎片率只有 5% 不到。這差距,可不是一星半點(diǎn)。
問題 2:36 個字符的 “空間黑洞”,太費(fèi)資源
UUID 是 36 個字符,要是用 VARCHAR (36) 存儲,每個 UUID 要占用 36 個字節(jié)(要是用 UTF-8 編碼,還可能更多)。咱們來算筆賬:
假設(shè)你有一張用戶表,有 1000 萬條數(shù)據(jù),主鍵是 UUID,那光主鍵索引就要占用 1000 萬 × 36 字節(jié) = 360MB。要是你再建幾個二級索引,比如 name、phone、email,每個二級索引里都要存主鍵的值,那每個二級索引又要多占 360MB,幾個索引加起來,光索引文件就好幾 GB 了。
要是換成自增 ID,用 BIGINT 類型(8 個字節(jié)),同樣 1000 萬條數(shù)據(jù),主鍵索引只需要 1000 萬 × 8 字節(jié) = 80MB,二級索引也跟著變小。同樣的磁盤空間,能裝下更多的數(shù)據(jù)和索引,查詢的時候內(nèi)存也能緩存更多索引,速度自然就快了。
有些同學(xué)可能會說 “我可以把 UUID 轉(zhuǎn)成二進(jìn)制存儲啊,這樣占用空間就小了”。沒錯,UUID 轉(zhuǎn)成二進(jìn)制是能從 36 字節(jié)降到 16 字節(jié),但還是比自增 ID 的 8 字節(jié)大一倍,而且還有個更麻煩的問題:查詢的時候你得把 UUID 轉(zhuǎn)成二進(jìn)制才能查,寫 SQL 的時候特別麻煩,比如where id = UNHEX('550e8400-e29b-41d4-a716-446655440000'),不僅容易寫錯,而且可讀性極差,后續(xù)維護(hù)的時候,同事看到這種 SQL 得罵娘。
問題 3:查詢性能差,尤其是范圍查詢
咱們平時查數(shù)據(jù),經(jīng)常會用范圍查詢,比如 “查昨天注冊的用戶”,要是主鍵是自增 ID,因?yàn)?ID 是有序的,InnoDB 直接就能定位到昨天的 ID 范圍,快速查出數(shù)據(jù)。
但要是主鍵是 UUID,ID 是無序的,就算你按主鍵范圍查,InnoDB 也得全表掃描(或者掃描大部分索引),因?yàn)樗恢肋@些 UUID 的范圍對應(yīng)的數(shù)據(jù)在哪里。我之前做過測試,查 “最近 1 萬條數(shù)據(jù)”,自增 ID 主鍵只需要 0.02 秒,而 UUID 主鍵需要 0.8 秒,慢了 40 倍!
那 UUID 就一點(diǎn)用都沒有了嗎?也不是。比如你在分布式系統(tǒng)里給文件命名、給緩存鍵命名,這些場景不需要存在 MySQL 里,也不需要排序,用 UUID 就很合適。但要是當(dāng) MySQL 主鍵,那還是算了吧,純屬給自己找罪受。
再聊雪花 ID:比 UUID 靠譜,但坑也不少
說完 UUID,咱們再說說雪花 ID。雪花 ID 是 Twitter 搞出來的一種分布式 ID 生成算法,結(jié)構(gòu)是 64 位的長整型(BIGINT),格式大概是這樣的:
- 1 位符號位:固定 0,因?yàn)?ID 是正數(shù)
- 41 位時間戳:能表示大概 69 年的時間(從某個起始時間開始算)
- 10 位機(jī)器 ID:能表示 1024 臺機(jī)器
- 12 位序列號:每臺機(jī)器每秒能生成 4096 個 ID(12 位最多 4095)
雪花 ID 的優(yōu)點(diǎn)很明顯:是有序的(因?yàn)橛袝r間戳)、占用空間?。? 字節(jié),和自增 ID 一樣)、能保證分布式環(huán)境下唯一,看起來好像完美符合 MySQL 主鍵的要求,那為啥我用雪花 ID 還會被領(lǐng)導(dǎo)懟呢?
別著急,雪花 ID 的坑,比你想象的要多。
問題 1:時鐘回?fù)苁?“致命傷”
雪花 ID 的有序性,全靠前面的 41 位時間戳。但要是生成 ID 的機(jī)器出現(xiàn) “時鐘回?fù)堋保闊┚痛罅恕?/p>
啥是時鐘回?fù)??就是機(jī)器的系統(tǒng)時間突然往后跳了,比如本來是 2025 年 8 月 25 日,突然變成 2025 年 8 月 24 日了。這可能是因?yàn)闄C(jī)器同步了 NTP 服務(wù)器時間,也可能是系統(tǒng)出了故障。
一旦發(fā)生時鐘回?fù)?,雪?ID 生成的時間戳就會比之前的小,生成的 ID 就會比之前的小,變成 “無序” 的。要是把這種無序的 ID 插進(jìn) MySQL,就會出現(xiàn)和 UUID 類似的問題:頁分裂、插入速度變慢。
更嚴(yán)重的是,要是時鐘回?fù)艿臅r間比較長,還可能生成重復(fù)的 ID。比如機(jī)器 A 在 8 月 25 日 10 點(diǎn)生成了一個 ID,然后時鐘回?fù)艿?8 月 25 日 9 點(diǎn),又生成了一個 ID,這兩個 ID 的時間戳、機(jī)器 ID、序列號都可能一樣,導(dǎo)致主鍵重復(fù),插入數(shù)據(jù)直接報(bào)錯。
我之前就遇到過這種情況:有個項(xiàng)目用了雪花 ID 當(dāng)主鍵,有一次服務(wù)器重啟后,NTP 同步時間,時鐘回?fù)芰?10 分鐘,結(jié)果當(dāng)天下午插入數(shù)據(jù)的時候,報(bào)了好幾百次主鍵沖突錯誤,查了半天才發(fā)現(xiàn)是時鐘回?fù)芨愕墓怼?/p>
那怎么解決時鐘回?fù)軉栴}呢?有幾種方案,但都不完美:
- 方案 1:檢測到時鐘回?fù)芫蜁和I?ID,等時間追上了再繼續(xù)。但這樣會導(dǎo)致服務(wù)暫時不可用,要是在高并發(fā)場景下,比如秒殺活動,這絕對是災(zāi)難。
- 方案 2:用物理時鐘 + 邏輯時鐘結(jié)合的方式,比如記錄上次生成 ID 的時間戳,要是當(dāng)前時間戳比上次小,就用上次的時間戳 + 1。但這樣會導(dǎo)致 ID 的時間戳和實(shí)際時間不一致,后續(xù)要是想通過 ID 判斷數(shù)據(jù)生成時間,就不準(zhǔn)了。
- 方案 3:多機(jī)房部署的時候,給每個機(jī)房分配不同的機(jī)器 ID 段,就算某個機(jī)房時鐘回?fù)?,也不會和其他機(jī)房的 ID 重復(fù)。但這需要復(fù)雜的配置和管理,小團(tuán)隊(duì)玩不轉(zhuǎn)。
不管哪種方案,都需要額外的開發(fā)和維護(hù)成本,不像自增 ID 那樣 “拿來就用,啥都不用管”。
問題 2:機(jī)器 ID 配置不當(dāng),分分鐘重復(fù)
雪花 ID 的 10 位機(jī)器 ID,能表示 1024 臺機(jī)器。但要是你配置機(jī)器 ID 的時候不小心,把兩臺機(jī)器配置成了同一個 ID,那這兩臺機(jī)器生成的雪花 ID 就會重復(fù),插入 MySQL 的時候就會報(bào)主鍵沖突。
我之前見過一個團(tuán)隊(duì),為了圖省事,直接用機(jī)器的 IP 地址最后幾位當(dāng)機(jī)器 ID。結(jié)果有一次擴(kuò)容,新增的機(jī)器 IP 最后幾位和之前的機(jī)器重復(fù)了,導(dǎo)致生成的雪花 ID 重復(fù),線上數(shù)據(jù)插入失敗,排查了 3 個小時才找到原因,最后還得回滾數(shù)據(jù),別提多狼狽了。
那機(jī)器 ID 該怎么配置呢?正確的做法是:
- 用 ZooKeeper、Etcd 這類分布式協(xié)調(diào)工具,給每臺機(jī)器分配唯一的機(jī)器 ID,機(jī)器啟動的時候去申請,關(guān)閉的時候釋放。
- 要是沒有分布式協(xié)調(diào)工具,也可以手動分配機(jī)器 ID 段,比如給 A 機(jī)房分配 0-100,B 機(jī)房分配 101-200,每臺機(jī)器在自己的段里選一個唯一的 ID。
但不管哪種方式,都需要額外的配置和維護(hù),不像自增 ID 那樣 “零配置”。
問題 3:在某些場景下,有序性也會出問題
雪花 ID 的有序性,是 “相對有序”,不是 “絕對有序”。因?yàn)樗呐判騼?yōu)先級是:時間戳 > 機(jī)器 ID > 序列號。
也就是說,在同一毫秒內(nèi),不同機(jī)器生成的 ID,會按機(jī)器 ID 排序;同一機(jī)器同一毫秒內(nèi)生成的 ID,會按序列號排序。
這在大部分場景下沒問題,但要是你有 “嚴(yán)格按生成時間排序” 的需求,就可能出問題。比如你有一個訂單表,要求訂單 ID 嚴(yán)格按下單時間排序,要是兩臺機(jī)器在同一毫秒內(nèi)生成訂單 ID,機(jī)器 ID 大的那個,就算下單時間稍晚,ID 也會更大,導(dǎo)致訂單 ID 的順序和實(shí)際下單時間的順序不一致。
雖然這種情況出現(xiàn)的概率不高,但要是你的業(yè)務(wù)對 ID 的時間順序要求特別嚴(yán)格(比如金融場景),那雪花 ID 就不太合適了。
問題 4:遷移數(shù)據(jù)的時候,能讓你哭
要是你用雪花 ID 當(dāng)主鍵,后續(xù)遷移數(shù)據(jù)的時候,比如把數(shù)據(jù)從舊庫遷到新庫,或者分庫分表,就會遇到一個麻煩:雪花 ID 是在應(yīng)用層生成的,不是數(shù)據(jù)庫生成的,所以遷移的時候,你得保證新庫的 ID 和舊庫一致,不能重復(fù),也不能漏。
而要是用自增 ID,數(shù)據(jù)庫會自動生成唯一的 ID,遷移的時候只需要把數(shù)據(jù)導(dǎo)過去就行,不用管 ID 的問題。
我之前參與過一個項(xiàng)目的數(shù)據(jù)庫遷移,用的就是雪花 ID 當(dāng)主鍵,結(jié)果遷移過程中,因?yàn)橛胁糠謹(jǐn)?shù)據(jù)的 ID 重復(fù),導(dǎo)致遷移失敗,最后不得不寫了個腳本,先把舊庫的 ID 全部導(dǎo)出來,再和新庫的 ID 對比,花了整整兩天才搞定,要是用自增 ID,半天就能搞定。
那 MySQL 主鍵到底該用啥?這 3 個方案才是王道
既然 UUID 和雪花 ID 當(dāng) MySQL 主鍵都有這么多坑,那到底該用啥呢?別著急,領(lǐng)導(dǎo)后來給我推薦了 3 個方案,親測好用,咱們一個個說。
方案 1:小項(xiàng)目 / 單機(jī)項(xiàng)目,自增 IDyyds
要是你的項(xiàng)目是小項(xiàng)目,或者不需要分布式部署,就一臺 MySQL 服務(wù)器,那自增 ID(AUTO_INCREMENT)絕對是最佳選擇,沒有之一。
自增 ID 的優(yōu)點(diǎn)太多了:
- 完全符合 MySQL 主鍵的三個要求:唯一(數(shù)據(jù)庫保證)、有序(每次 + 1)、占用空間小(8 字節(jié))。
- 零配置:不用自己寫代碼生成 ID,數(shù)據(jù)庫自動搞定,省事兒。
- 性能好:插入速度快,查詢速度快,索引碎片少。
- 方便遷移:遷移數(shù)據(jù)的時候不用管 ID,數(shù)據(jù)庫自動生成。
那自增 ID 就沒缺點(diǎn)嗎?也有,比如:
- 分布式環(huán)境下不唯一:要是你有多個 MySQL 實(shí)例,每個實(shí)例都自增,就會出現(xiàn)重復(fù)的 ID。
- 容易被猜到:比如你的用戶 ID 是自增的,別人很容易猜到你有多少用戶,也容易通過 ID 遍歷數(shù)據(jù)(比如從 1 開始,依次訪問 /user/1、/user/2)。
但對于小項(xiàng)目 / 單機(jī)項(xiàng)目來說,這些缺點(diǎn)根本不是問題。比如你做一個企業(yè)內(nèi)部的管理系統(tǒng),就一臺 MySQL 服務(wù)器,用戶量也就幾千人,用自增 ID 完全沒問題,簡單又高效。
方案 2:分布式項(xiàng)目,數(shù)據(jù)庫分段自增 ID 更靠譜
要是你的項(xiàng)目是分布式的,需要多臺 MySQL 服務(wù)器(比如分庫分表),自增 ID 就不夠用了,這時候可以用 “數(shù)據(jù)庫分段自增 ID”。
啥是數(shù)據(jù)庫分段自增 ID?簡單說就是:專門建一個 “ID 生成器” 數(shù)據(jù)庫,里面有一張表,記錄每個業(yè)務(wù)表的 ID 當(dāng)前最大值和步長,每次應(yīng)用需要生成 ID 的時候,就去這個表拿一段 ID(比如拿 1000 個),然后在應(yīng)用里自己慢慢用,用完了再去拿下一段。
舉個例子,比如用戶表的 ID:
- 先建一個 ID 生成器表:
CREATE TABLE id_generator (
table_name VARCHAR(50) NOT NULL COMMENT '業(yè)務(wù)表名',
current_max_id BIGINT NOT NULL COMMENT '當(dāng)前最大ID',
step INT NOT NULL COMMENT '步長',
PRIMARY KEY (table_name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT 'ID生成器表';- 初始化用戶表的 ID 配置:
INSERT INTO id_generator (table_name, current_max_id, step) VALUES ('user', 0, 1000);- 應(yīng)用需要生成用戶 ID 的時候,先執(zhí)行以下 SQL,拿一段 ID(0-999):
UPDATE id_generator
SET current_max_id = current_max_id + step
WHERE table_name = 'user'
AND current_max_id = 0;- 應(yīng)用拿到這段 ID 后,就可以從 0 開始,依次生成 0、1、2……999,用完了再去拿下一段(1000-1999)。
這種方案的優(yōu)點(diǎn):
- 有序性:ID 是連續(xù)的,符合 MySQL 主鍵的要求,不會出現(xiàn)頁分裂。
- 分布式唯一:因?yàn)樗袘?yīng)用都從同一個 ID 生成器拿 ID,所以不會重復(fù)。
- 性能好:每次拿一段 ID,不用每次生成 ID 都訪問數(shù)據(jù)庫,減少數(shù)據(jù)庫壓力。
- 配置簡單:不用依賴 ZooKeeper、Etcd 這些分布式協(xié)調(diào)工具,只需要一個數(shù)據(jù)庫就行。
缺點(diǎn)也有,就是 ID 生成器數(shù)據(jù)庫是單點(diǎn),要是這個數(shù)據(jù)庫掛了,所有需要生成 ID 的業(yè)務(wù)都得停。不過可以搞主從復(fù)制,主庫掛了就切從庫,解決單點(diǎn)問題。
我之前參與的一個電商項(xiàng)目,用的就是這種方案,分了 10 個庫,每個庫有 10 個表,每天新增訂單 100 多萬,用數(shù)據(jù)庫分段自增 ID,從來沒出現(xiàn)過 ID 重復(fù)或者性能問題,特別穩(wěn)定。
方案 3:高并發(fā)場景,Redis 生成 ID 也不錯
要是你的項(xiàng)目并發(fā)特別高,比如秒殺活動,每秒要生成幾萬甚至幾十萬的 ID,數(shù)據(jù)庫分段自增 ID 可能會有點(diǎn)吃力(因?yàn)槊看文枚?ID 都要訪問數(shù)據(jù)庫),這時候可以用 Redis 生成 ID。
Redis 生成 ID 的原理很簡單:利用 Redis 的 INCR 命令(原子性遞增),每次生成 ID 的時候,就調(diào)用 INCR 命令,讓某個鍵的值加 1,這個值就是新的 ID。
比如生成用戶 ID:
- 先在 Redis 里設(shè)置一個鍵,初始值為 0:
SET user_id 0- 每次需要生成用戶 ID 的時候,調(diào)用 INCR 命令:
INCR user_id這樣每次調(diào)用 INCR,都會返回一個唯一的、有序的 ID。為了提高性能,也可以像數(shù)據(jù)庫分段自增那樣,一次性從 Redis 拿一段 ID,比如拿 1000 個:
INCRBY user_id 1000這樣就能拿到一段 ID(比如從 1001 到 2000),然后在應(yīng)用里自己慢慢用。Redis 生成 ID 的優(yōu)點(diǎn):
- 性能極高:Redis 是內(nèi)存數(shù)據(jù)庫,INCR 命令的性能特別好,每秒能處理幾十萬次請求,完全能滿足高并發(fā)場景。
- 有序性:ID 是連續(xù)遞增的,符合 MySQL 主鍵要求。
- 分布式唯一:所有應(yīng)用都訪問同一個 Redis,不會出現(xiàn) ID 重復(fù)。
缺點(diǎn):
- 需要依賴 Redis:要是 Redis 掛了,ID 生成就會出問題,所以得搞 Redis 集群,保證高可用。
- 數(shù)據(jù)持久化問題:要是 Redis 沒有持久化,或者持久化失敗,Redis 重啟后,ID 會從之前的值開始,可能會重復(fù)。所以需要開啟 Redis 的 AOF 持久化,并且配置合適的持久化策略。
這種方案適合高并發(fā)場景,比如秒殺、直播帶貨這些需要快速生成大量 ID 的業(yè)務(wù)。我之前做過一個秒殺項(xiàng)目,每秒并發(fā) 10 萬 +,用 Redis 生成訂單 ID,特別穩(wěn)定,從來沒掉過鏈子。
總結(jié):別再盲目跟風(fēng),選對主鍵才是王道
看到這里,你應(yīng)該明白為啥我用雪花 ID 當(dāng) MySQL 主鍵會被領(lǐng)導(dǎo)懟了吧?不是雪花 ID 不好,也不是 UUID 不好,而是它們不適合當(dāng) MySQL 主鍵。
選 MySQL 主鍵,就像選鞋子,不是越貴越好,也不是越高級越好,而是要合腳??偨Y(jié)一下:
- 小項(xiàng)目 / 單機(jī)項(xiàng)目:直接用自增 ID,簡單高效,不用瞎折騰。
- 分布式項(xiàng)目(中低并發(fā)):用數(shù)據(jù)庫分段自增 ID,穩(wěn)定可靠,配置簡單。
- 分布式項(xiàng)目(高并發(fā)):用 Redis 生成 ID,性能極高,能扛住大流量。
- 要是你實(shí)在想用雪花 ID:那一定要做好時鐘回?fù)芴幚砗蜋C(jī)器 ID 配置,并且接受它可能帶來的遷移麻煩和排序問題。
- 至于 UUID:除非你腦子進(jìn)水了,否則別把它當(dāng) MySQL 主鍵。
技術(shù)沒有好壞之分,只有合適不合適。別看到別人用雪花 ID、用 UUID,你就跟著用,得先搞明白背后的原理,結(jié)合自己的業(yè)務(wù)場景,才能做出正確的選擇。不然哪天被領(lǐng)導(dǎo)懟了,還不知道為啥,多冤?。?/p>































