在分布式系统中,需要对大量的数据、消息、请求等进行唯一的标识,例如分布式数据库的ID需要满足唯一且多数据库同步,在单一系统中,使用数据库自增主键可以满足需求,但是在分布式系统中就需要一个能够生成全局唯一ID的系统,而且还要满足高可用。
数据库自增长字段
本文只整理MySQL的自增字段方案,Oracle和SQL Server的自增长方案就不介绍了。
MySQL自增列使用auto_increment标识字段达到自增,在创建表时将某一列定义为auto_increment,则改列为自增列。这定了auto_increment的列必须建立索引。
auto_increment使用说明
如果把一个NULL插入到一个auto_increment数据列中,MySQL将自动生成下一个序列编号。编号从1开始,并以1为基数递增;
把0插入auto_increment数据列的效果与插入NULL值一样,但是不建议这样做,还是以插入NULL值为好;
当插入记录时,没有为auto_increment明确指定值,则等同于插入NULL值;
当插入记录时,如果为auto_increment数据列明确指定了一个数值,则会出现两种情况,情况一,如果插入的值与已有的编号重复,则会出现出错信息,因为auto_increment数据列的值必须是唯一的;情况二,如果插入的值大于已编号的值,则会把该值插入到数据列中,并使在下一个编号将这个新值开始递增。也即可以跳过一些编号;
如果用update命令更新自增列,如果列值与已有的值重复,则会出错。如果大于已有值,则下一个编号从该值开始递增。
相关配置MySQL中的自增长字段,在做数据库的主主同步时需要在参数文件中设置自增长的两个相关配置:
auto_increment:自增长字段从哪个数开始,取值范围是:1~65535
auto_increment_increment:自增长字段每次递增的量,即步长,默认值是1,取值范围是1~65535
优化方案:在配置集群的MySQL时,需要将n台服务器的auto_increment_increment都配置为n,而要把auto_increment_offset分别配置为1,2,……,n。这样才可以避免多台服务器更新时自增长字段的值之间出现冲突。
优缺点 优点:
很小的数据存储空间,简单,代码方便,性能可以接受
数字ID天然排序,容易记忆,对分页或者需要排序的结果很有帮助
缺点:
如果存在大量的数据,可能会超出自增长的取值范围
在单个数据库或读写分离或一主多从的情况下,只有一个主库可以生成,有单点故障的风险
很难处理分布式存储的数据表,尤其是需要合并表的情况下
安全性低,因为是有规律的,容易被非法获取数据
UUID
UUID全称是Universally Unique Identifier,即通用唯一识别码。
UUID是由一组32位数的16进制数字所构成,所以理论上UUID的总数为16^32=2^128,约等于3.4*10^38。
UUID的标准形式包括32个16进制数字,以连字号分为5段,例如:1FA504B0-2F82-21D3-0A0C-1205E72C3301。UUID经由一定的算法机器生成,为了保证UUID的唯一性,规范定义了包括网卡MAC地址、时间戳、名字空间、随机数或伪随机数、时序等元素,以及从这些元素生成UUID的算法。
优缺点 优点
本地生成ID,不需要进行远程调用,时延低,性能好
缺点
UUID过长,16字节共128位,通常以36长度的字符串标识,很多场景不适用,比如用UUID做数据库索引字段
没有排序,无法保证趋势递增
不可读
UUID的变种 UUID to Int64
为了解决UUID不可读的问题,可以使用UUID to Int64的方法。