大数据时代,自增长的主键形式已经完全不能满足现有的业务,很早便使用UUID主键形式,但是弊端是太长,

EG:   7174f86a-b569-4b85-b303-0135d839c5a9

高达36位之巨-_-#,即便处理掉了横杠也有32位,这也不是一个小数目。

看了比特币采用Base58的主键形式,感觉非常良好,相关地址:https://en.bitcoin.it/wiki/Base58Check_encoding

它的算法源码文件为:https://code.google.com/p/bitcoinj/source/browse/core/src/main/java/com/google/bitcoin/core/Base58.java

项目jar 下载地址为https://code.google.com/p/bitcoinj/downloads/list  但是一直未能成功,难道是天朝的原因么:-D

那么就自己动手抄抄吧 :)
Base58.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package org.ne.framework.data.util;
 
public class Base58 {
 
	private static final char[] ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
			.toCharArray();
	private static final int BASE_58 = ALPHABET.length;
	private static final int BASE_256 = 256;
 
	private static final int[] INDEXES = new int[128];
	static {
		for (int i = 0; i < INDEXES.length; i++) {
			INDEXES[i] = -1;
		}
		for (int i = 0; i < ALPHABET.length; i++) {
			INDEXES[ALPHABET[i]] = i;
		}
	}
 
	public static String encode(byte[] input) {
		if (input.length == 0) {
			// paying with the same coin
			return "";
		}
 
		//
		// Make a copy of the input since we are going to modify it.
		//
		input = copyOfRange(input, 0, input.length);
 
		//
		// Count leading zeroes
		//
		int zeroCount = 0;
		while (zeroCount < input.length && input[zeroCount] == 0) {
			++zeroCount;
		}
 
		//
		// The actual encoding
		//
		byte[] temp = new byte[input.length * 2];
		int j = temp.length;
 
		int startAt = zeroCount;
		while (startAt < input.length) {
			byte mod = divmod58(input, startAt);
			if (input[startAt] == 0) {
				++startAt;
			}
 
			temp[--j] = (byte) ALPHABET[mod];
		}
 
		//
		// Strip extra '1' if any
		//
		while (j < temp.length && temp[j] == ALPHABET[0]) {
			++j;
		}
 
		//
		// Add as many leading '1' as there were leading zeros.
		//
		while (--zeroCount >= 0) {
			temp[--j] = (byte) ALPHABET[0];
		}
 
		byte[] output = copyOfRange(temp, j, temp.length);
		return new String(output);
	}
 
	public static byte[] decode(String input) {
		if (input.length() == 0) {
			// paying with the same coin
			return new byte[0];
		}
 
		byte[] input58 = new byte[input.length()];
		//
		// Transform the String to a base58 byte sequence
		//
		for (int i = 0; i < input.length(); ++i) {
			char c = input.charAt(i);
 
			int digit58 = -1;
			if (c >= 0 && c < 128) {
				digit58 = INDEXES[c];
			}
			if (digit58 < 0) {
				throw new RuntimeException("Not a Base58 input: " + input);
			}
 
			input58[i] = (byte) digit58;
		}
 
		//
		// Count leading zeroes
		//
		int zeroCount = 0;
		while (zeroCount < input58.length && input58[zeroCount] == 0) {
			++zeroCount;
		}
 
		//
		// The encoding
		//
		byte[] temp = new byte[input.length()];
		int j = temp.length;
 
		int startAt = zeroCount;
		while (startAt < input58.length) {
			byte mod = divmod256(input58, startAt);
			if (input58[startAt] == 0) {
				++startAt;
			}
 
			temp[--j] = mod;
		}
 
		//
		// Do no add extra leading zeroes, move j to first non null byte.
		//
		while (j < temp.length && temp[j] == 0) {
			++j;
		}
 
		return copyOfRange(temp, j - zeroCount, temp.length);
	}
 
	private static byte divmod58(byte[] number, int startAt) {
		int remainder = 0;
		for (int i = startAt; i < number.length; i++) {
			int digit256 = (int) number[i] & 0xFF;
			int temp = remainder * BASE_256 + digit256;
			number[i] = (byte) (temp / BASE_58);
			remainder = temp % BASE_58;
		}
 
		return (byte) remainder;
	}
 
	private static byte divmod256(byte[] number58, int startAt) {
		int remainder = 0;
		for (int i = startAt; i < number58.length; i++) {
			int digit58 = (int) number58[i] & 0xFF;
			int temp = remainder * BASE_58 + digit58;
			number58[i] = (byte) (temp / BASE_256);
			remainder = temp % BASE_256;
		}
 
		return (byte) remainder;
	}
 
	private static byte[] copyOfRange(byte[] source, int from, int to) {
		byte[] range = new byte[to - from];
		System.arraycopy(source, from, range, 0, range.length);
		return range;
	}
}

那么压缩UUID部分片段如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static String compressedUUID(UUID uuid) {
		byte[] byUuid = new byte[16];
		long least = uuid.getLeastSignificantBits();
		long most = uuid.getMostSignificantBits();
		long2bytes(most, byUuid, 0);
		long2bytes(least, byUuid, 8);
		String compressUUID = Base58.encode(byUuid);
		return compressUUID;
	}
protected static void long2bytes(long value, byte[] bytes, int offset) {
		for (int i = 7; i > -1; i--) {
			bytes[offset++] = (byte) ((value >> 8 * i) & 0xFF);
		}
	}

那么压缩出来的主键为22位,大大节省了存储和传输的效率,小样如下:
5Tg43HoVDUSwaF6yBf1qKY
3obyeMUYU6oYp97XbNzKuV
ChcHGBEvBw7JRM74i7yQAz
81ARiYeZaUyQTB6LTfdfAh
GtphVs8QZkyoBTcHTTpm5C
2q8jAT773mrsD8o1u2Rq4E
UTEuYET1ip9FUJbtJB4dy2
TFeEHsUXzJadFR1R22tGH2
3mFwsDFbhRQdDQ6cMTLYCd
P5CYVqutjRcr9bERUWE6RZ
SQYnrVq97cMNkb51UMNmQT