在很多小项目中,我们往往直接使用数据库自增特性来生成主键ID,这样确实比较简单。而在分库分表的环境下,数据分布在不同的数据表中,不能再借助数据库自增特性直接生成,否则会造成不同数据表主键重复。下面介绍集中ID生成算法。
UUID
UUID是通用唯一标识码(Universally Unique Identifier)的缩写,长度是16个字节,被表示为32个十六进制数字,以‘-’分隔的五组来显示,格式为8-4-4-4-12,共36个字符,例如:be277cf0-9fed-433e-b958-eb82e8c0f142。UUID在在生成时使用到了以太网地址、纳秒级时间、芯片ID和随机数等信息,目的是让分布式系统中的所有元素都能有唯一的标示信息。
使用UUID作主键,可以在本地生成,没有网络消耗,所以性能非常高。但是UUID比较长,没有规律性,消耗存储空间。
All indexes other thantheclustered index are known as secondary indexes.In innoDB,each record in secondary index contains the primary key columns for the row, as the columns specified for the secondary index.InnoDB uses this primary key value to search for the row in the clustered index.If the primary key is long,the secondary indexes use more space,so it is advantageous to have a short primary key.
除聚集索引意外的所有索引都为辅助索引,在InnoDB中,二级索引中的每条记录都包含行的主键列,以及为二级索引指定的列。在InnoDB使用这个主键值来搜索聚集索引的行。如果主键是长的,则次级索引使用更多的空间,因此主键短是有利的。
COMB(UUID变种)
COMB(combine)型是数据库特有的一种设计思想,可以理解为一种改进的GUID,它通过组合GUID和系统时间,以使其在索引和检索时更有性能优势,数据库中没有COMB类型,它是Jimmy Nilsson在它的“The Cost of GUID as Primay Keys”一文中设计出来的。
COMB设计思路是这样的:既然UniqueIdentifier数据因毫无规律可言而造成效率低下,影响了系统的性能,那么我们能不能通过组合的方式,保留UniqueIdentifier的前10个字节,用后6个字节表示GUID生成的时间(DateTime),这样我们将时间信息与UniqueIdentifier组合起来,在保留UniqueIdentifier的唯一性的同时增加了有序性,以此来提高索引的效率。解决了UUID的无序问题,性能优与UUID。
SnowFlake
有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成,SnowFlake解决了这种需求。SnowFlake是Twitter开源的分布式ID生成算法,结果是一个long型的ID,long型是8个字节,64-bit。其核心思想是:使用41bit作为毫秒数,10bit作为及其的ID(5个bit是数据中心,5个bit的及其ID),12bit作为毫秒内的流水号,最后还有一个符号位,永远是0.
SnowFlake生成的ID整体上按照时间自增排序,并且整个分布式系统内不会产生ID重复,而且效率较高。经测试SnowFlake每秒能够产生26万个ID。缺点是强依赖机器时钟,如果多台及其环境时钟没有同步,或者时钟回拨,会导致发号重复或者服务会处于不可用状态。因此一些互联网公司也基于上述的方案做了封装,例如百度的uidgenerator(基于SnowFlake)和美团的leaf(基于数据库和SnowFlake)等。
数据库ID表
比如A表分表为A1和A2,我们可以单独的创建一个MySQL数据库,在这个数据库中创建一张表,这张表的ID设置为自动递增,其他地方需要全局唯一ID的时候,就先向这个表中模拟插入一条记录,此时ID就会自动递增,然后我们可以使用刚刚获取的ID作为所需要的ID写入A1或A2表。
Redis生成
可以利用Redis的单线模型的优势来生成全局唯一的ID,调用redis的incr自增方法来生成。