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
