最近发现公司用的公共jar包里生成惟一主键的方法居然用的是当前时间戳,这种方式有明显弊端,参考了网上各类生成惟一id的方式以后,作下总结。java
1、数据库自增IDmysql
使用mysql数据库的自增id,数据库的自增id的优势是很是明显的:第一是速度快,并且是按序自增,检索很是有利。第二是自增的id都是数字型,占用空间小,易于程序中排序。 第三是新增记录时能够不用指定id,不用担忧主键重复问题。
算法
固然,使用数据库自增ID也有缺点:第一是手动插入指定ID的记录时会比较麻烦。第二是当新老系统合并作数据迁移时,新旧系统都是数字型,会致使多个主键id冲突,或新旧系统主键不一样是数字型就会致使修改主键数据类型。第三若是ID是连续的,恶意用户的扒取工做就很是容易作了,直接按照顺序下载指定URL便可;若是是订单号就更危险了,竞对能够直接知道咱们一天的单量。因此在一些应用场景下,会须要ID无规则、不规则。sql
2、UUID数据库
UUID保证对在同一时空中的全部机器都是惟一的。UUID由如下几部分的组合:
(1)当前日期和时间,UUID的第一个部分与时间有关,若是你在生成一个UUID以后,过几秒又生成一个UUID,则第一个部分不一样,其他相同。
(2)时钟序列。
(3)全局惟一的IEEE机器识别号,若是有网卡,从网卡MAC地址得到,没有网卡以其余方式得到。
数组
java中提供了两个对应的方法:安全
randomUUID() ,适用于生成惟一订单号。 服务器
nameUUIDFromBytes(byte[] n)会根据n产生惟一的uuid。只要有用户的惟一性信息。就能保证此用户的uuid的惟一性。网络
优势:性能很是高:本地生成,没有网络消耗。app
缺点:第一是不易存储,UUID太长,16字节128位,一般以36长度的字符串表示,不少场景不适用。第二是信息不安全,基于MAC地址生成UUID的算法可能会形成MAC地址泄露,这个漏洞曾被用于寻找梅丽莎病毒的制做者位置。
下面是UUID及生成8位UUID的java实例:
public class UUIDTest {
public static String[] chars = new String[]
{
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
};
public static void main(String[] args) {
System.out.println(UUID.randomUUID().toString().replace("-", ""));
System.out.println(getShortUuid());
}
public static String getShortUuid() {
StringBuffer stringBuffer = new StringBuffer();
String uuid = UUID.randomUUID().toString().replace("-", "");
for (int i = 0; i < 8; i++) {
String str = uuid.substring(i * 4, i * 4 + 4);
int strInteger = Integer.parseInt(str, 16);
stringBuffer.append(chars[strInteger % 0x3E]);
}
return stringBuffer.toString();
}
}复制代码
其中生成8位UUID的思路是:将32位UUID按每四位截取,将截取的每组字符串转换成10进制的数字,而后对0x3E(十进制为62)取余,根据取余获得的结果找到ASCII字符数组中(总共62个字符)的位置,将每组的结果拼接就获得一个8位的UUID字符串。
3、SnowFlake雪花算法
雪花ID生成的是一个64位的二进制正整数,而后转换成10进制的数。64位二进制数由以下部分组成:
优势
缺点