基於UUID生成短ID

爲何須要短ID

數據庫操做過程最經常使用到:java

  • 自增ID
  • UUID

前者多數依賴Mysql的auto_increment,但數據移植麻煩. 若是是主從或主主,不一樣庫裏自增ID還可能不一致.sql

後者長度是個問題.數據庫

怎樣生成短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);
    }

}

生成結果:dom

  • 32進制,5bit一個字符, 64bit大約12~13個字符.
  • 用64進制, 6bit一個字符, 64bit大約11~12個字符

循環1000W,碰撞率爲0.ui

相關文章
相關標籤/搜索