Uuid、数据库自增、雪花算法、基于redis自研等数据库唯一ID生成策略对比
使用环境
分布式、高并发下全局唯一,趋势递增,效率高,控制并发
先直接上个对比图吧,下面大量干货警告
一、Uuid(java1.5后自带生成工具类)
Uuid是按照开放软件基金会(osf)制定的标准计算用到了以太网开地址(MAC),纳米级时间,芯片id码和许多可能的数字
优点:
使用简单
不依赖其他组件
不影响数据库拓展
缺点:
数据库索引效率低
太过于无意义.用户不友好
长度36的字符串,空间占用大
应用集群环境,机器多的时候,重复几率大
使用方法
import java.util.UUID;
public class UTest {
public static void main(String[] args) {
UUID uuid = UUID.randomUUID();//生成的类型为uuid类型
String s = UUID.randomUUID().toString();//经过toString后可直接赋值到id上实现存储
System.out.println(uuid);
System.out.println(s);
}
}
也可以适当的自定义内容
public class UUIDGenerator {
public UUIDGenerator() {
}
/**
* 获得一个UUID
* @return String UUID
*/
public static String getUUID(){
String s = UUID.randomUUID().toString();
//去掉“-”符号
return s.substring(0,8)+s.substring(9,13)+s.substring(14,18)+s.substring(19,23)+s.substring(24);
}
/**
* 获得指定数目的UUID
* @param number int 需要获得的UUID数量
* @return String[] UUID数组
*/
public static String[] getUUID(int number){
if(number < 1){
return null;
}
String[] ss = new String[number];
for(int i=0;i<number;i++){
ss[i] = getUUID();
}
return ss;
}
public static void main(String[] args){
String[] ss = getUUID(10);
for(int i=0;i<ss.length;i++){
System.out.println(ss[i]);
}
}
}
二、数据库自增
Mysql 整型自增索引之所以快是因为mysql 采用b+树对整型进行了加速
Mysql使用auto_increment, oracle使用sequence序列
集群环境下,不同的库,设置不同的初始值,每次自增加 100
Mysql下修改起点和步长的方式
设置起点
Set @@auto_increment_offset=1 // 设置起点为1
设置步长
Set@@auto_increment_increment=100 // 设置步长为100
查看参数
show VARIABLES like 'auto_%' // 查看参数
优点:
无需编码
性能也过得去
索引友好
缺点:
大表不能做水平分表,否则插入删除易出现问题(已经存在很大数据的时候再分表,容易出现问题)
依赖前期规划,拓展麻烦
依赖mysql内部维护自增锁,高并发下插入数据影响性能
在业务操作父,子(关联表)插入时,要先父表 后子表
相对于uuid 其实 数据库自增表的效率稍低
特点是 : 互斥 排他 可重入
CREATE TABLE TABLE_1
( ID INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, // ID列为无符号整型,该列值不可以为空,并不可以重复,而且自增。
NAME VARCHAR(5) NOT NULL )
AUTO_INCREMENT = 100;
三、雪花算法(snowflake算法)
Snowfake算法是twitter’开源的分布式id生成算法,结果就是long长整型的id
优点:
性能较优,速度快
无需第三方依赖,实现也简单
可以根据实际情况调整和拓展算法,方便灵活 (开源)
缺点:
依赖时间机器,如果发生回拨会导致生成id重复,业界使用一般是根据雪花算法进行拓展的
(可以把这个服务单独做成一个服务用于生成id,但是会连累生成效率)
源码
package com.cnblogs.util;
/**
* Twitter_Snowflake<br>
* SnowFlake的结构如下(每部分用-分开):<br>
* 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 <br>
* 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0<br>
* 41位时间戳(毫秒级),注意,41位时间戳不是存储当前时间的时间戳,而是存储时间戳的差值(当前时间戳 - 开始时间戳)
* 得到的值),这里的的开始时间戳,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。41位的时间戳,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69<br>
* 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId<br>
* 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间戳)产生4096个ID序号<br>
* 加起来刚好64位,为一个Long型。<br&g