一个短的唯一id生成方法,解决uuid过长的问题
2015-12-18 14:10
1081 查看
前言:最近,在做用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位的,可以如法炮制
多次执行,均未打印发现重复数字。
上面的Base64是从android中的android.util.Base64复制过来的代码。
生成的部分端key如下:
hN6xJRChnAc=
l+HS8MQDhjQ=
ockqqV25yao=
h+0TnvoDQIU=
ZEm4IvX+62g=
vkHGQwWElwE=
XcJwkva5Q1o=
KDxMLTGwUmc=
根据评论内容作了一些调整:
上面代码注释已经很清楚了。可以提前用随机数生成好数据放到数据池里面,这样子的话,可以减轻一下随机算法的压力,而且更加严谨,保证了每秒内不会有重复的字符串
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; }
上面代码注释已经很清楚了。可以提前用随机数生成好数据放到数据池里面,这样子的话,可以减轻一下随机算法的压力,而且更加严谨,保证了每秒内不会有重复的字符串
相关文章推荐
- extjs每个组件要设置唯一的ID否则会出错
- android关于获取手机唯一码的组合文章
- mysql 获取全局唯一值
- php订单生成唯一Id
- 给大数据文件的每一行产生唯一的id
- IT技术:唯一ID高效率生成方式
- redis生成唯一id
- Zookeeper学习(七):ZooKeeper 实现命名服务(系统唯一ID)
- PHP生成唯一ID的三种方法
- 几种获取Android手机唯一id的方法
- 用golang生成6位数的唯一id
- 记一次生成唯一ID的问题
- Twitter的分布式自增ID算法snowflake - C#版
- UUID唯一标识生成器
- HIVE下分布式生成整型唯一ID
- 生成一个唯一的Id
- ID生成器
- 分布式系统唯一ID生成方案汇总
- IOS 第一帖关于无法拿到唯一识别码的方法
- 解决视图(SQL查询语句)唯一ID问题