前言:最近,在做用redis存储用户消息的时候,采用的结构如下:
Key value
Msg+userId+time 消息内容
但是如果在同一时间里面,有很多人并发发送了消息给用户怎么办呢?也就是说只是在key后面加时间
我的时间格式是yyyy-MM-ddHH:mm:ss,这样子万一有重复key怎么办,消息就会被覆盖了
于是想到在后面加uuid,但是uuid有30多位啊,我只需要简单的短的一个避免重复的id就可以了。
于是写了下面代码,并做了测试,发现在100次,每次生成10万条的情况下,都没有重复,这里没有测试100万,1000万条,因为我觉得如果你需要在这种极端情况下的话,你还是需要使用长的uuid的。
下面是8位的短id,基本可以抵抗10万条重复,如果需要9位,11位,16位的,可以如法炮制
public static void main(String args[]){
byte []bytes=new byte[8];
Random random=new Random();
HashSet<String>hash=new HashSet<>();
for(int j=0;j<100;j++) {
hash.clear();
for (int i = 0; i < 100000; i++) {
random.nextBytes(bytes);
String s = Base64.encodeToString(bytes, Base64.DEFAULT);
//System.out.println(s);
if (hash.contains(s)) {
System.out.println("发现重复数字" + i);
break;
}
hash.add(s);
}
}
多次执行,均未打印发现重复数字。
上面的Base64是从android中的android.util.Base64复制过来的代码。
生成的部分端key如下:
hN6xJRChnAc=
l+HS8MQDhjQ=
ockqqV25yao=
h+0TnvoDQIU=
ZEm4IvX+62g=
vkHGQwWElwE=
XcJwkva5Q1o=
KDxMLTGwUmc=
根据评论内容作了一些调整:
public static volatile long time;
private static volatile int nums=0;
private static List<String> poolStrings;
static {
//初始你的数据池poolStrings,这里你可以从1-100000,直接数字初始化都可以
//或者按照上面的随机串初始化,但是要保证list里面的数据是非重复的,切记。
}
/*
该方法主要保证一秒内获取的字符都是非重复的
*/
public static String generate(){
//如果nums为0的话,说明是首次取数字,记录下当前的时间,如果当前时间减去记录时间超过一秒了
//那么重新从数据池里面取数字,重置记录时间
if(nums==0||System.currentTimeMillis()-time>=1000){
time=System.currentTimeMillis();
}
int size=poolStrings.size();
//如果nums的数量等于数据池的大小了,而且当前时间距离记录时间还没过去一秒
//说明已经超出你的每秒的随机需求了,这时候你需要正视你的软件的每秒压力
//来调整数据池的大小。
if(nums==size&&System.currentTimeMillis()-time<1000){
throw new RuntimeException("每秒需求的随机数超过了你的数据池");
}
//正常取数字
String randomString=poolStrings.get(nums);
//对数字+1
nums++;
return randomString;
}
来源:oschina
链接:https://my.oschina.net/u/999017/blog/547281