RandomStringUtils.randomAlphannumeric(30)是有效的GUID策略吗



我需要一个随机字符串生成器,该生成器生成一个字母数字字符串,以便在30个字符或更少的分布式系统中用作唯一键。它不能包含任何特殊字符。

RandomStringUtils#randomAlphannumeric对此有效吗?

底层实现使用java.util.Random

唯一密钥集可能不到1000亿,系统需要能够每秒处理多达1000条记录。

我如何证明这种策略具有足够低的碰撞概率,可以作为主键生成器工作?

java.util.Random实现了一个LCG算法,它的周期是2^48个数字,因此RandomStringUtils将与此实现一样好,1000亿个30个字符的字符串将需要大约1%的2^48随机元素。

请注意,java.util.Random在加密方面是不安全的,所以给定一些GUID,就可以推断下一个GUID,所以我会使用另一个使用加密安全随机数生成器的实现(例如java.util.SecureRandom)。

为什么不想使用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));
   }
} 

Random不是唯一的。使用随机数生成来获得"唯一"值会遇到生日问题https://en.wikipedia.org/wiki/Birthday_attack.这将把1/2^48的概率变成1/2^24的概率,你最终会打出比你想象的更快的球。使用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("=", "");

相关内容

  • 没有找到相关文章

最新更新