searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

java 生成22位UUID改造

2023-06-12 06:17:41
50
0

背景:数据库的前期设计,主键用的是 uuid,但这个是大数据量的应用。经过 n 久的折腾,数据大于 1 亿条了。返回去看表,发现,表的很多字段是 varchar2 的,但是长度不超过 20 字符。占据大部分空间的居然是 uuid。于是萌生改造 uuid 的想法。

大概思路:uuid 用 64 进制改造,把 uuid 生成的字符串去掉 “-”,再补一个 “0”,得到 33 位的 16 进制数,再用 22 个 64 进制数表示。利用 uuid 生成的 mostSigBits、leastSigBits 来做位移,再通过 base64 的算法将 16 字节的 2 个 long 类型转换成字符。

核心过程:

  1. 把字符串用 md5 转为 16 个字节,然后生成 UUID,UUID 里有 msb,lsb 两个 64bit 的 long 类型数字
  2. 把 lsb|msb 当做一个 128bit 的数字
  3. 最终看是要生成 22 位字符还是 20 位字符,用 64 进制表示,映射到 64 个字符上
  4. 如果是 22 位,就是 22*6 = 12bit0 lsb 前 8 位 4bit0 lsb 后 56 位 msb = 0000 0000 0000 8bit 0000 24bit 24bit 24bit (8+16) 24bit 24bit
  5. 如果是 20 位(es 生成的 id 就是 20 位),就是 20*6 =120 = lsb 后 56 位 msb,简单点就是 lsb 前 8 位不要了,或者这 8 位可以做点位操作,比如异或之类的,这里代码不涉及

出版代码写法是 24bit 24bit = 000000 000000 000000 000000 000000 000000 000000 000000 = out [4] out [5] out [6] out [7] out [0] out [1] out [2] out [3],这样写代码就很难写

现在的写法是 24bit 24bit = 000000 000000 000000 000000 000000 000000 000000 000000 = out [7] out [6] out [5] out [4] out [3] out [2] out [1] out [0],也就是按顺序,每 6bit 放到一个 out 里面,看着就舒服多了,效果一样的,只是字符顺序换了一下,写代码更简洁。

说完原理上代码

	public static String getUUID(String str, int size) {
		UUID uuid = UUID.nameUUIDFromBytes(str.getBytes());
		long msb = uuid.getMostSignificantBits();
		long lsb = uuid.getLeastSignificantBits();
		char[] out = new char[size];
		// 0000 0000 0000 8bit 0000 24bit 24bit 24bit(8+16) 24bit 24bit
		long tmp = msb;
		int idx = 0;
		int value;
		while (tmp != 0) {
			value = (int) tmp & 0xffffff;
			for (int i = 0; i < 4; i++) {
				out[idx++] = alphabet[value & 0x3f];
				value >>= 6;
			}
			// msb不够用了,补上lsb的48位
			if (tmp >>> 24 == 0 && lsb >>> 48 != 0) {
				tmp = lsb << 16 | tmp;
				lsb = lsb >>> 48;
			}
			tmp = tmp >>> 24;
		}
		if (size == 22) {
			value = (int) (lsb << 4);
			out[idx++] = alphabet[value & 0x3f];
			value >>= 6;
			out[idx] = alphabet[value & 0x3f];
		}
		return new String(out);
	}

	public static void main(String[] args) {
		String str = "this is a test string";
		System.out.println(getUUID(str, 20));
		System.out.println(getUUID(str, 22));
	}
0条评论
0 / 1000
柯****武
2文章数
0粉丝数
柯****武
2 文章 | 0 粉丝
柯****武
2文章数
0粉丝数
柯****武
2 文章 | 0 粉丝
原创

java 生成22位UUID改造

2023-06-12 06:17:41
50
0

背景:数据库的前期设计,主键用的是 uuid,但这个是大数据量的应用。经过 n 久的折腾,数据大于 1 亿条了。返回去看表,发现,表的很多字段是 varchar2 的,但是长度不超过 20 字符。占据大部分空间的居然是 uuid。于是萌生改造 uuid 的想法。

大概思路:uuid 用 64 进制改造,把 uuid 生成的字符串去掉 “-”,再补一个 “0”,得到 33 位的 16 进制数,再用 22 个 64 进制数表示。利用 uuid 生成的 mostSigBits、leastSigBits 来做位移,再通过 base64 的算法将 16 字节的 2 个 long 类型转换成字符。

核心过程:

  1. 把字符串用 md5 转为 16 个字节,然后生成 UUID,UUID 里有 msb,lsb 两个 64bit 的 long 类型数字
  2. 把 lsb|msb 当做一个 128bit 的数字
  3. 最终看是要生成 22 位字符还是 20 位字符,用 64 进制表示,映射到 64 个字符上
  4. 如果是 22 位,就是 22*6 = 12bit0 lsb 前 8 位 4bit0 lsb 后 56 位 msb = 0000 0000 0000 8bit 0000 24bit 24bit 24bit (8+16) 24bit 24bit
  5. 如果是 20 位(es 生成的 id 就是 20 位),就是 20*6 =120 = lsb 后 56 位 msb,简单点就是 lsb 前 8 位不要了,或者这 8 位可以做点位操作,比如异或之类的,这里代码不涉及

出版代码写法是 24bit 24bit = 000000 000000 000000 000000 000000 000000 000000 000000 = out [4] out [5] out [6] out [7] out [0] out [1] out [2] out [3],这样写代码就很难写

现在的写法是 24bit 24bit = 000000 000000 000000 000000 000000 000000 000000 000000 = out [7] out [6] out [5] out [4] out [3] out [2] out [1] out [0],也就是按顺序,每 6bit 放到一个 out 里面,看着就舒服多了,效果一样的,只是字符顺序换了一下,写代码更简洁。

说完原理上代码

	public static String getUUID(String str, int size) {
		UUID uuid = UUID.nameUUIDFromBytes(str.getBytes());
		long msb = uuid.getMostSignificantBits();
		long lsb = uuid.getLeastSignificantBits();
		char[] out = new char[size];
		// 0000 0000 0000 8bit 0000 24bit 24bit 24bit(8+16) 24bit 24bit
		long tmp = msb;
		int idx = 0;
		int value;
		while (tmp != 0) {
			value = (int) tmp & 0xffffff;
			for (int i = 0; i < 4; i++) {
				out[idx++] = alphabet[value & 0x3f];
				value >>= 6;
			}
			// msb不够用了,补上lsb的48位
			if (tmp >>> 24 == 0 && lsb >>> 48 != 0) {
				tmp = lsb << 16 | tmp;
				lsb = lsb >>> 48;
			}
			tmp = tmp >>> 24;
		}
		if (size == 22) {
			value = (int) (lsb << 4);
			out[idx++] = alphabet[value & 0x3f];
			value >>= 6;
			out[idx] = alphabet[value & 0x3f];
		}
		return new String(out);
	}

	public static void main(String[] args) {
		String str = "this is a test string";
		System.out.println(getUUID(str, 20));
		System.out.println(getUUID(str, 22));
	}
文章来自个人专栏
文章 | 订阅
0条评论
0 / 1000
请输入你的评论
0
0