首頁 > 軟體

Mysql分庫分表之後主鍵處理的幾種方法

2022-02-15 13:02:56

資料庫自增 ID

搞一個資料庫,什麼也不幹,就用於生成主鍵。

你的系統裡每次得到一個 id,都需要往那個專門生成主鍵的資料庫中通過插入獲取一個自增的ID,拿到這個 id 之後再往對應的分庫分表裡去寫入。

優點:方便簡單。

缺點單庫生成自增 id,要是高並行的話,就會有瓶頸的;如果你硬是要改進一下,那麼就專門開一個服務出來,這個服務每次就拿到當前 id 最大值,然後自己遞增幾個 id,一次性返回一批 id,然後再把當前最大 id 值修改成遞增幾個 id 之後的一個值;但是無論如何都是基於單個資料庫。

適合的場景:系統並行不大,只是因為資料量大的原因而去做的分庫分表的話,可以採用這種方式。

設定資料庫 sequence 或者表自增欄位步長

可以通過設定資料庫 sequence 或者表的自增欄位步長來進行水平伸縮。

比如說,現在有 8 個服務節點,每個服務節點使用一個 sequence 功能來產生 ID,每個 sequence 的起始 ID 不同,並且依次遞增,步長都是8

適合的場景:在使用者防止產生的 ID 重複時,這種方案實現起來比較簡單,也能達到效能目標。但是服務節點固定,步長也固定,將來如果還要增加服務節點,就不好搞了。

UUID

優點:本地生成,不需要基於資料庫;

缺點:UUID 太長了、佔用空間大;作為主鍵效能太差:UUID 不具有有序性,會導致 B+ 樹索引在寫的時候有過多的隨機寫操作(連續的 ID 可以產生部分順序寫),還有,由於在寫的時候不能產生有順序的 append 操作,而需要進行 insert 操作,導致頻繁的進行頁分裂,效能下降明顯。

適合的場景:如果你是要隨機生成個什麼檔名、編號之類的,你可以用 UUID,但是作為InnoDB表的主鍵是不能用 UUID 的。

UUID.randomUUID().toString().replace(「-」, 「」) -> sfsdf23423rr234sfdaf

系統當前時間戳+XXX

適合的場景:一般如果用這個方案,是將當前時間戳跟很多其他的業務欄位拼接起來,作為一個 id,如果業務上你覺得可以接受,那麼也是可以的。你可以將別的業務欄位值跟當前時間拼接起來,組成一個全域性唯一的編號。

Snowflake 演演算法

snowflake 演演算法是 twitter 開源的分散式 id 生成演演算法,採用 Scala 語言實現,是把一個 64 位的 long 型的 id,1 個 bit 是不用的,用其中的 41 bit 作為時間戳(毫秒數),用 10 bit 作為工作機器 id,12 bit 作為序列號。

  • 1 bit:不用,為啥呢?因為二進位制裡第一個 bit 為如果是 1,那麼都是負數,但是我們生成的 id 都是正數,所以第一個 bit 統一都是 0。
  • 41 bit:表示的是時間戳,單位是毫秒。41 bit 可以表示的數位多達 2^41 - 1,也就是可以標識 2^41 - 1 個毫秒值,換算成年就是表示69年的時間。
  • 10 bit:記錄工作機器 id,代表的是這個服務最多可以部署在 2^10臺機器上哪,也就是1024臺機器。但是 10 bit 裡 5 個 bit 代表機房 id,5 個 bit 代表機器 id。意思就是最多代表 2^5個機房(32個機房),每個機房裡可以代表 2^5 個機器(32臺機器)。
  • 12 bit:這個是用來記錄同一個毫秒內產生的不同 id,12 bit 可以代表的最大正整數是 2^12 - 1 = 4096,也就是說可以用這個 12 bit 代表的數位來區分同一個毫秒內的 4096 個不同的 id。
0 | 0001100 10100010 10111110 10001001 01011100 00 | 10001 | 1 1001 | 0000 00000000

到此這篇關於Mysql分庫分表之後主鍵處理的幾種方法的文章就介紹到這了,更多相關Mysql分庫分表主鍵內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com