zoukankan      html  css  js  c++  java
  • 全局唯一ID的生成方式

    一、程序直接生成:
    使用jdk中的concurrent包可以轻松实现唯一数字型ID的生成,且无需考虑单例、采用高效率的CAS无需考虑synchronized关键字
    import java.util.concurrent.atomic.AtomicLong;
    
    public class UniqueID {
    	private static AtomicLong uniqeid = new AtomicLong(0);
    
    	public static long getNextID() {
    		return uniqeid.getAndIncrement();
    	}
    
    	public static void main(String[] agrs) {
    		System.out.println(getNextID());
    	}
    }
    缺点:
    1、基于内存,如果服务器重启则id会重新从0开始;
    2、无法解决分布式的问题:基于单虚拟机,如果多虚拟机的话也有问题;
    3、如果ID过于庞大,可能会导致溢出


    二、借助第三方资源:数据库或者memcache
    比如可以借助Oracle的SEQUENSE或者mysql的AUTO_INCREMENT来实现数字型ID的自增序列
    优点:
    1、有效的解决了分布式的问题
    2、做好了持久化,解决了重启或者服务器挂掉导致的ID丢失问题
    缺点:
    1、每次获取都需要查询数据库,如果这个极为频繁的话会有性能上的瓶颈
    2、数字型ID,可能溢出,不过这个最大值已经非常庞大,基本可以忽略
    这个方法还可以延伸为使用memcache来充当数据库的角色,而且memcache天生支持CAS操作,效率上应该比数据库要好,但是牺牲了它的第二个优点,无法持久化


    三、使用UUID:由jdk或借助第三方来提供
    JDK的UUID提供了生成128位唯一ID(如“055b158a-e0ad-43f3-b2cd-702e31219191”)的接口,使用其伪随机的randomUUID()方法可以得到如下代码
    import java.util.UUID;
    
    public class JdkUUIDUniqueValue {
    	public static String getNextID() {
    		return UUID.randomUUID().toString();
    	}
    
    	public static void main(String[] args) {
    		System.out.println(getNextID());
    	}
    }
    也可以由以下几种方式来完成这项工作:
    mysql的uuid()函数:select uuid();
    oracle的内置函数:select sys_guid() from dual;
    hibernate也有uuid的实现方式
    优点:
    1、完全无状态,无需任何的同步,无需任何的持久化,分布式也无妨
    缺点:
    1、在理论上仍然有重复的可能性,虽然这种可能性极小
    2、ID以长字符串的形式出现,可读性差,且需要更多的存储,在排序等相关操作中需要更多的资源


    四、使用服务器系统时间、随机数、其他已知元素作为因子进行组合
    这种情况一般都是为了考虑效率问题,既不想使用第三方资源,也不想使用uuid这么长的无意义字符串,或者还有其他特殊需求,比如必须是多少位的数字,再比如这个ID只在某一段时间内有效过了时间之后需要重新回到起点循环等。
    例如:时间戳+随机数;
    import java.util.Date;
    import java.util.Random;
    
    public class MyUniqueID {
    	private static long getUniqueId() {
    		long cur = new Date().getTime();
    		int random = new Random().nextInt(1000000);
    		return Long.valueOf(cur + random);
    	}
    
    	public static void main(String[] args) {
    		System.out.println(getUniqueId());
    	}
    }
    这个在性能上非常理想了,但是时间戳这个东西实在有些问题,能拿到到底精确到什么程度的时间戳,如果只能到毫秒一级还真是有些风险的,或许可以通过增加随机数的位数来降低重复的概率,但是仍然有重复的可能性,而且也难保系统时间会不会由于外部原因发生变化。不过对于请求量较小且可以容忍非常偶尔的重复率的场景,应该是个不错的选择。



  • 相关阅读:
    COJ 0981 WZJ的数据结构(负十九)树综合
    BZOJ 3153 Sone1
    点分治模板
    thinkphp或thinkcmf 《文章编辑,文章添加》 访问另一个表的分类,添加入另一个表时将id值以(,)逗号分隔储存,编辑时以(,)逗号分隔并且相等的id值被选中
    《手机端》让多出的导航变水平拖动,不让他 float 撑下去
    favicon.ico 网站小图标标识
    CSS3实战开发: 折角效果实战开发
    jquery怎么在点击li标签之后添加一个在class,点击下一个li时删除上一个class?
    position 有五个值:static、relative、absolute、fixed、inherit。
    CSS3 transition 属性过渡效果 详解
  • 原文地址:https://www.cnblogs.com/suncoolcat/p/3291955.html
Copyright © 2011-2022 走看看