UUID是通用唯一标识符的缩写,是一个软件构建的标准,它使用长度为128位(16字节)的值来表示信息。UUID可以保证对在同一时空中的所有机器都是唯一的,它实际上上是利用网络上的时间和计算机MAC地址来生成的。
一、UUID的优点
1、全球唯一性
String uuid = UUID.randomUUID().toString().replaceAll("-", ""); System.out.println(uuid);
UUID采用128位编码,标识信息的唯一性,长时间不重复,保证了对于海量数据处理时,不会产生冲突。
2、无序性
UUID uuid1 = UUID.randomUUID(); UUID uuid2 = UUID.randomUUID(); System.out.println(uuid1.compareTo(uuid2));
UUID采用无序性的编码,这个特性可以避免数据库在写入数据时,需要枷锁和解锁的操作,显著提升了开发效率。
3、方便存储和传输
UUID uuid = UUID.randomUUID(); ByteBuffer buffer = ByteBuffer.wrap(new byte[16]); buffer.putLong(uuid.getMostSignificantBits()); buffer.putLong(uuid.getLeastSignificantBits()); byte[] array = buffer.array();
UUID仅使用128位,方便对任意平台和数据库进行数据存储和传送。
二、UUID的使用
1、获取UUID
UUID uuid = UUID.randomUUID(); System.out.println(uuid.toString());
UUID类提供了randomUUID()方法,可以用于获取一个UUID对象。
2、UUID的表示
UUID uuid = UUID.fromString("38400000-8cf0-11bd-b23e-10b96e4ef00d"); System.out.println(uuid.getLeastSignificantBits());
通过fromString()方法可以将字符串转化成UUID对象,其中的连字符是可选的,但建议保留,这样可以方便读取。
3、UUID的比较
UUID uuid1 = UUID.fromString("38400000-8cf0-11bd-b23e-10b96e4ef00d"); UUID uuid2 = UUID.fromString("38400000-8cf0-11bd-b23e-10b96e4ef00d"); System.out.println(uuid1.equals(uuid2));
UUID类提供了equals()、compareTo()等方法,用于比较两个UUID的大小是否相等,或者两个UUID是否相等,如果相等则返回0。
三、UUID生成算法
1、时间戳
private static long toUnixTime(long timeStamp) { return (timeStamp - START_EPOCH) * 10000 + 0x01b21dd213814000L; } private static long timeToMillis(long time) { return (time - 0x01b21dd213814000L) / 10000 + START_EPOCH; } private static final long START_EPOCH; static { Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); calendar.set(1582, Calendar.OCTOBER, 15, 0, 0, 0); calendar.set(Calendar.MILLISECOND, 0); START_EPOCH = calendar.getTimeInMillis(); } private static long createTimestamp() { long timestamp = System.currentTimeMillis(); long time = toUnixTime(timestamp); return time; }
UUID生成的过程中,会生成一个时间戳,通过时间戳可以保证生成的UUID在不同时间生成时不会重复。在Java中,可以使用System.currentTimeMillis()方法获取一个毫秒级别的时间戳。
2、MAC地址
private static long createNode() { InetAddress address; try { address = InetAddress.getLocalHost(); } catch (UnknownHostException e) { throw new RuntimeException(e); } byte[] mac = null; try { mac = NetworkInterface.getByInetAddress(address).getHardwareAddress(); } catch (SocketException e) { throw new RuntimeException(e); } if (mac == null) { return 0xffffffffffffL; } long node = 0; for (int i = 0; i < mac.length; i++) { node |= ((long) mac[i] & 0xff) << (8 * (5 - i)); } return node; }
UUID生成的过程中,还会用到机器的MAC地址,通过MAC地址可以保证生成的UUID在同一时间内,在不同机器上也不会重复。
3、随机数
private static long createRandom() { SecureRandom random = new SecureRandom(); byte[] bytes = new byte[8]; random.nextBytes(bytes); return ((long) bytes[0] & 0xff) << 56 | ((long) bytes[1] & 0xff) << 48 | ((long) bytes[2] & 0xff) << 40 | ((long) bytes[3] & 0xff) << 32 | ((long) bytes[4] & 0xff) << 24 | ((long) bytes[5] & 0xff) << 16 | ((long) bytes[6] & 0xff) << 8 | ((long) bytes[7] & 0xff); }
UUID生成的过程中,还会用到随机数,通过随机数的存在,可以保证生成的UUID的唯一性。
四、UUID的应用场景
1、主键
在数据库中,通常将主键设计成UUID,可以避免业务层和数据层之间的耦合,更容易扩展。
2、文件名
在上传文件时,可以将文件名设置成UUID,可以避免出现重名文件,而且易于管理。
3、网络通信
在分布式系统中,可以使用UUID来定义一致的消息格式,方便不同系统之间的通信。
五、总结
UUID是一个通用唯一标识符,具有全球唯一性、无序性、方便传输等优点,可以应用于主键、文件名、网络通信等场景。UUID的生成需要时间戳、MAC地址和随机数的支持,可以采用UUID类提供的方法获取UUID对象,也可以自己编写生成算法。