我需要一个随机字符串生成器,它生成一个字母数字字符串,用作30 个字符或更少字符的分布式系统中的唯一键。它不能包含任何特殊字符。
RandomStringUtils #randomAlphanumeric会为此工作吗?
底层实现使用java.util.Random
.
唯一键的集合可能少于 1000 亿个,并且系统需要能够每秒处理多达 1000 条记录。
我如何证明该策略具有足够低的冲突概率以用作主键生成器?
我需要一个随机字符串生成器,它生成一个字母数字字符串,用作30 个字符或更少字符的分布式系统中的唯一键。它不能包含任何特殊字符。
RandomStringUtils #randomAlphanumeric会为此工作吗?
底层实现使用java.util.Random
.
唯一键的集合可能少于 1000 亿个,并且系统需要能够每秒处理多达 1000 条记录。
我如何证明该策略具有足够低的冲突概率以用作主键生成器?
java.util.Random 实现了一个 LCG 算法,它的周期是 2^48 个数字,所以 RandomStringUtils 将和这个实现一样好,1000 亿个 30 个字符的字符串需要 2^48 个随机元素的 1%。
请注意,java.util.Random 不是加密安全的,因此给定一些 GUID 可以推断下一个,因此我将使用另一个使用加密安全随机数生成器的实现(例如 java.util.SecureRandom)。
随机不是唯一的。使用随机数生成来获取“唯一”值会遇到生日问题https://en.wikipedia.org/wiki/Birthday_attack。这会将 2^48 中的 1 概率转换为 2^24 中的 1 概率,您最终会比您想象的更快地击中。使用 UUID;它们被设计为具有普遍的独特性。
32 个字符:
UUID.randomUUID().toString.replace("-","")
22 个字符:
UUID uuid = UUID.randomUUID();
String uuidStr = Base64.encodeBase64URLSafeString(ByteBuffer.wrap(new byte[16])
.putLong(uuid.getMostSignificantBits())
.putLong(uuid.getLeastSignificantBits())
.array()).replace("=", "");
为什么你不想使用java.util.UUID
类?它返回 32 位字符串的随机 UUID。示例实现:
import java.util.UUID;
public class GenerateUUID {
public static final void main(String... aArgs){
//generate random UUIDs
UUID idOne = UUID.randomUUID();
UUID idTwo = UUID.randomUUID();
log("UUID One: " + idOne);
log("UUID Two: " + idTwo);
}
private static void log(Object aObject){
System.out.println(String.valueOf(aObject));
}
}