基于UUID生成短ID

为什么需要短ID

数据库操作过程最常用到:

  • 自增ID
  • UUID

前者多数依赖Mysql的auto_increment,但数据移植麻烦. 如果是主从或主主,不同库里自增ID还可能不一致.

后者长度是个问题.

怎样生成短ID

  • 生成UUID
  • 哈希murmur为64bit
  • 使用64进制显示
public class ClientShardInfo {

	public static void main(String[] args) {

		Map<Long, Integer> result = new HashMap<>();
		long start = System.currentTimeMillis();
		for (int i = 0; i < 10000 * 100; i++) {
			long hash = nextShortId();
			System.out.println(Long.toUnsignedString(hash, 32));
			Integer val = result.get(hash);
			if (val == null) {
				val = 1;
			} else {
				val++;
			}
			result.put(hash, val);
		}
		long end = System.currentTimeMillis();
		System.out.println("used time:" + (end - start));
		System.out.println(result);
	}

	public static long nextShortId() {
		UUID uuid = UUID.randomUUID();
		long h = uuid.getMostSignificantBits();
		long l = uuid.getLeastSignificantBits();

		byte[] bytes = new byte[16];
		bytes[0] = (byte) ((h >>> 56) & 0xFF);
		bytes[1] = (byte) ((h >>> 48) & 0xFF);
		bytes[2] = (byte) ((h >>> 40) & 0xFF);
		bytes[3] = (byte) ((h >>> 32) & 0xFF);
		bytes[4] = (byte) ((h >>> 24) & 0xFF);
		bytes[5] = (byte) ((h >>> 16) & 0xFF);
		bytes[6] = (byte) ((h >>> 8) & 0xFF);
		bytes[7] = (byte) (h & 0xFF);

		bytes[8] = (byte) ((l >>> 56) & 0xFF);
		bytes[9] = (byte) ((l >>> 48) & 0xFF);
		bytes[10] = (byte) ((l >>> 40) & 0xFF);
		bytes[11] = (byte) ((l >>> 32) & 0xFF);
		bytes[12] = (byte) ((l >>> 24) & 0xFF);
		bytes[13] = (byte) ((l >>> 16) & 0xFF);
		bytes[14] = (byte) ((l >>> 8) & 0xFF);
		bytes[15] = (byte) (l & 0xFF);

		return Hashing.MURMUR_HASH.hash(bytes);
	}

}

生成结果:

  • 32进制,5bit一个字符, 64bit大约12~13个字符.
  • 用64进制, 6bit一个字符, 64bit大约11~12个字符

循环1000W,碰撞率为0.

posted @ 2016-08-30 16:47  zolo®  阅读(1067)  评论(0编辑  收藏  举报