一个短的唯一id生成方法,解决uuid过长的问题

爱⌒轻易说出口 提交于 2020-04-06 21:54:00

前言:最近,在做用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;

    }



上面代码注释已经很清楚了。可以提前用随机数生成好数据放到数据池里面,这样子的话,可以减轻一下随机算法的压力,而且更加严谨,保证了每秒内不会有重复的字符串

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!