1.UUID (Universally Unique Identifier),通用唯一识别码。UUID是基于当前时间、计数器(counter)和硬件标识(通常为无线网卡的MAC地址)等数据计算生成的。
UUID由以下几部分的组合:
1.当前日期和时间,UUID的第一个部分与时间有关,如果你在生成一个UUID之后,过几秒又生成一个UUID,则第一个部分不同,其余相同。
2.时钟序列。
3.全局唯一的IEEE机器识别号,如果有网卡,从网卡MAC地址获得,没有网卡以其他方式获得。
UUID 是由一组32位数的16进制数字所构成,以连字号分隔的五组来显示,形式为 8-4-4-4-12,总共有 36个字符(即三十二个英数字母和四个连字号)。例如:
aefbbd3a-9cc5-4655-8363-a2a43e6e6c80
xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
如果需求是只保证唯一性,那么UUID也是可以使用的,但是按照上面的分布式id的要求, UUID其实是不能做成分布式id的,原因如下:
1.首先分布式id一般都会作为主键,但是安装mysql官方推荐主键要尽量越短越好,UUID每一个都很长,所以不是很推荐。
2.既然分布式id是主键,然后主键是包含索引的,然后mysql的索引是通过b+树来实现的,每一次新的UUID数据的插入,为了查询的优化,都会对索引底层的b+树进行修改,因为UUID数据是无序的,所以每一次UUID数据的插入都会对主键生成的b+树进行很大的修改,这一点很不好。
3.信息不安全:基于MAC地址生成UUID的算法可能会造成MAC地址泄露,这个漏洞曾被用于寻找梅丽莎病毒的制作者位置。
这种方式在单个数据库的场景中是可以这样做的,但如果是在分库分表的环境下。直接利用单个数据库的自增肯定会出现问题。因为ID要唯一,但是分表分库后只能保证一个表中的ID的唯一,而不能保证整体的ID唯一。
上面的情况我们可以通过单独创建主键维护表来处理。
单点数据库方式存在明显的性能问题,可以对数据库进行优化,担心一个主节点挂掉没法使用,可以选择做双主模式集群,也就是两个MySQL实例都能单独生产自增的ID。
可以设置主键自增的步长从2开始:
这种在并发量比较高的情况下,如何保证扩展性其实会是一个问题。在高并发情况下无能为力。
例如 (1,1000] 代表1000个ID,具体的业务服务将本号段,生成1~1000的自增ID并加载到内存。表结构如下:
CREATE TABLE id_generator (
id int(10) NOT NULL,
max_id bigint(20) NOT NULL COMMENT '当前最大id',
step int(20) NOT NULL COMMENT '号段的布长',
biz_type int(20) NOT NULL COMMENT '业务类型',
version int(20) NOT NULL COMMENT '版本号',
PRIMARY KEY (`id`) )