1.UUID生成
通过网卡、时间、随机数来保证生成的唯一的字符串。 优点: (1)本地生成,生成简单 (2)速度快 (3)高可用; 缺点: (1)无序,如果存入mysq,影响B+的操作性能,因为B+树是需要排序的; (2)占用空间较大(36个字符);
2.数据库自增长
优点: (1)生成简单; (2)严格递增; 缺点: (1)性能较差 (2)可靠性较差。
3.通过mysql批量生成
记录max_id,然后通过update t set max_id=max_id+step where max_id=last_id;这种乐观锁更新的方式保证唯一性,然后可以提前生成两批放在本地内存中,能够提升性能。 优点: (1)相比方案2性能更佳; 缺点: (1)还是依赖数据库的稳定性; (2)因为id是一批批存在本地服务器中的,如果服务器重启可能造成id不连续。
4.使用redis的incr来生成
优点:性能较高 缺点:redis如果出现问题,可能导致id重复
5.雪花算法:
实现原理:总共64个2二进制位:从左往右 第一位为固定的0,代表正整数 接下来的41位表示时间戳,精确到毫秒,值为当前时间戳-算法开始时间戳; 接下来10位用来表示机器的机房id、机器编号; 接下来的12位用来表示同一毫秒的自增序号。 这个算法的关键是如何生成机房id,和机器编号 其实有两种方案 (1)通过redis来生成,通过lua脚本来保证原子性:使用hash结构,有两个key,一个是机房id ,一个是机器id,刚开始机房id=0,机器id=0,服务启动的时候,先判断机器id是否等于31了?如果等于则机房id+1,机器id设置为0,循环往复; (2)通过生成zk的永久顺序节点,不过现在很多都是容器启动,ip地址会变,就会导致生成很多节点,最好还是换成临时顺序节点; 优点: (1)本地生成,性能较高,按时间有序; 缺点: (1)强依赖机器时间。
6.美团的leaf
主要支持两种模式,一种是方案3,一种是方案5。 针对方案5的时钟问题,leaf做了处理,要求每台机器需要上报时间到zk上面,然后来校验时间是否变化,这种我感觉并没有彻底解决这个问题。