订单号3个性质:1.唯一性 2.不可推测性 3.效率性
可选方案一 本方案使用的是当前时间,包括毫秒数、纳秒数,不需要数据库参与计算,性能不用说。
public static String genId(String machineId){
String orderId =
machineId +
(System.currentTimeMillis() + "").substring(1) +
(System.nanoTime() + "").substring(7, 10); System.out.println(orderId); return orderId;}
讲解:参数machineId:是集群时的机器代码,可以1-9任意。部署时,分别为部署的项目手动修改该值,以确保集群的多台机器在系统时间上不一致的问题(毫无疑问每台机器的毫秒数基本上不一致)。参数System.currentTimeMillis():这是java里面的获取1970年到目前的毫秒数,是一个13位数的数字,与Date.getTime()函数的结果一样,比如1378049585093。经过研究,在2013年,前三位是137,在2023年是168,到2033年才199.所以,我决定第一位数字1可以去掉,不要占位置了。可以肯定绝大多数系统用不了10年20年。这样,参数2就变成了12位数的数字,加上参数1machineId才13位数。参数System.nanoTime():这是java里面的取纳秒数,经过深入研究,在同一毫秒内,位置7,8,9这三个数字是会变化的。所以决定截取这三个数字出来拼接成一个16位数的订单号。总结:理论上此方案在同一秒内,可以应对1000*1000个订单号,但是经过测试,在每秒并发2000的时候,还是会出现2-10个重复。
可选方案二本方案基于UUID。UUID是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的,这个不重复性全世界人民都知道。当然,既然字符串值不重复,那对应的hashCode也是一样,不会重复。算法:
Java代码OrderId=
machineId+
UUID.randomUUID().toString().hashCode();
讲解:参数1不再解释。参数2是值生成UUID然后取它的hashCode值,经过测试,完全没有一点问题。您可以开1000w的并发去测试插入吧,只要数据库不会报唯一性错误,那就没问题。总结:hashCode这个算法从搞软件开始到现在这么多年,一直没派上用场,这次大大的用上了。解决了问题。请同志们以后善用这个东西。5、 附录:方案二的算法代码
public static String getOrderIdByUUId(String machineId) { int hashCodeV = UUID.randomUUID().toString().hashCode();
if (hashCodeV
String orderId=machineId + String.format("%015d", hashCodeV); System.out.println(orderId); return orderId;
}
方案二其实也就一个函数,很简便。