MySQL的id生成策略


1 自增

CREATE TABLE `test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

---------------------------------------------------------------------------------

問題1:單點問題,如果分表分庫不能保證id唯一。

解決1:部署兩個(多個)數據庫實例,設置自增步長為2(多個則為實例數),即auto-increment-increment = 2,設置auto-increment-offset分別為1,2.....
這樣第一台數據庫服務器的自增id為 1 3 5 7 9,第二台為2 4 6 8 10。

---------------------------------------------------------------------------------

問題2:自增鎖(AUTO_INC鎖)。mysql5.1.22之前,當表里有一個auto_increment字段的時候,innoDB會在內存里保存一個計數器用來記錄auto_increment的值,當插入一個新行數據時,就會用一個表鎖來鎖住這個計數器,直到插入結束。如果大量的並發插入,表鎖會引起SQL堵塞。

解決1:id不使用自增,可以使用uuid等其他方式生成(后文詳述)。

解決2:在mysql5.1.22之后,InnoDB為了解決自增主鍵鎖表的問題,引入了參數innodb_autoinc_lock_mode,該實現方式是通過輕量級互斥量的增長機制完成的。用來在使用auto_increment的情況下調整鎖策略。該參數可以設置三個值:0、1、2

0:traditonal 通過表鎖的方式進行,所有類型的insert都用AUTO-inc locking。

1:consecutive 默認值,產生一個輕量鎖,對於simple insert 自增長值的產生使用互斥量對內存中的計數器進行累加操作,對於bulk insert 則還是使用表鎖的方式進行。

2:interleaved 對所有的insert-like 自增長值的產生使用互斥量機制完成,並發性能最高,並發插入可能導致自增值不連續,可能會導致Statement 的 Replication 出現不一致,使用該模式,需要用 Row Replication的模式。

 

2 UUID

點擊uuid詳情

優點:沒有自增鎖的問題,也沒有單點問題,實現簡單。

問題:由於UUID非常的長,除占用大量存儲空間外,最主要的問題是在索引上,在建立索引和基於索引進行查詢時都存在性能問題。

 

3 自己維護一個Sequence表

CREATE TABLE `SEQUENCE` (  
    `table_name` varchar(18) NOT NULL,  
    `nextid` bigint(20) NOT NULL,  
    PRIMARY KEY (`table_name`)  
) ENGINE=InnoDB

每當需要為某個表的新紀錄生成ID時就從Sequence表中取出對應表的nextid,並將nextid的值加1后更新到數據庫中以備下次使用。

優點:沒有自增鎖問題。

問題:由於所有插入任何都需要訪問該表,該表很容易成為系統性能瓶頸,同時它也存在單點問題,一旦該表數據庫失效,整個應用程序將無法工作。

解決:使用Master-Slave進行主從同步,但這也只能解決單點問題,並不能解決讀寫比為1:1的訪問壓力問題。

 

4 twitter的snowflake算法

介紹:分布式系統中,有一些需要使用全局唯一ID的場景,這種時候為了防止ID沖突可以使用36位的UUID,但是UUID有一些缺點,首先他相對比較長,另外UUID一般是無序的。

有些時候我們希望能使用一種簡單一些的ID,並且希望ID能夠按照時間有序生成。而twitter的snowflake解決了這種需求,最初Twitter把存儲系統從MySQL遷移到Cassandra,因為Cassandra沒有順序ID生成機制,所以開發了這樣一套全局唯一ID生成服務。

snowflake的結構如下(每部分用-分開):

0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000

第一位為未使用,接下來的41位為毫秒級時間(41位的長度可以使用69年),然后是5位datacenterId和5位workerId(10位的長度最多支持部署1024個節點) ,最后12位是毫秒內的計數(12位的計數順序號支持每個節點每毫秒產生4096個ID序號),一共加起來剛好64位,為一個Long型。(轉換成字符串后長度最多19)。

snowflake生成的ID整體上按照時間自增排序,並且整個分布式系統內不會產生ID碰撞(由datacenter和workerId作區分),並且效率較高。經測試snowflake每秒能夠產生26萬個ID。

 

參考:https://www.cnblogs.com/jshen/p/7682502.html

https://www.cnblogs.com/relucent/p/4955340.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM