分布式ID的简单实现

在上一篇博文(JDK自带UUID的性能问题)中我提到的一个满足我们需求,并能代替UUID的分布式ID的方案。在这里我做了简单的实现。

实现如下:
8位用作机器名
50位用作timestamp
6位用作标识符
 

用8位表示机器,可以表示256台机器。
50位表示的timestamp(毫秒),一年31536000000毫秒,可以表示35702年。
6位标识符,标识符只有在同一时间点上有两次ID的请求时会用到,用来区别这两个ID.6位表示64,也就是说只要你请求ID的TPS<64000,就不会有问题。

经过我简单的测试,这个实现在单线程下性能要比JDK自带UUID好一个数量级。在多线程下就更不用说了,因为我这个实现没有用同步。不过这两个本身也没有可比性。

import java.util.concurrent.atomic.AtomicLong;

/**
 * This class is used for generating unique id in a distributed environment. 
 * It require a server identifier. Server identifier is a 0-255 integer.
 * DistributedID(64 bits) = ServerID(8) + Time(50) + clk_seq(6)
 * @author "Peter Lu"
 */
public class DistributedID {
	
    /**
     * The last time value. Used to remove duplicate IDs.
     */
    private final static AtomicLong lastTime = new AtomicLong(Long.MIN_VALUE);
    
    /**
     * generate distributed ID. 
     * 
     * @param serverIdentifier support 256 servers. 0-255
     * @return
     */
    public static String getDistributedID(int serverIdentifier) {
    	
    	long dentifier = (long)serverIdentifier << 56;
    	
    	long distributedID = dentifier | genTimeBasedID();
    	
    	String id = Long.toHexString(distributedID);
    	
    	while(id.length()<16) {
    		id = "0" + id;
    	}
    	
    	return id;
    }
    
	/**
     * Generates a new time field. Each time field is unique and larger than the
     * previously generated time field. 
	 * @return
	 */
	private static long genTimeBasedID() {
		return genTimeBasedID(System.currentTimeMillis());
	}
    
	/**
     * generate a new time field from the given timestamp. Note that even identical
     * values of <code>time</code> will produce different time fields.
	 * @param time
	 * @return
	 */
	private static long genTimeBasedID(long time) {
		
		// 6 bits for clk_seq
		time = time << 6;
		
		// try again if compareAndSet failed
		while(true) {
			long tempTime = lastTime.get();
			if(time>tempTime) {
				if(lastTime.compareAndSet(tempTime, time)) {
					break;
				}
			} else {
				// +1 to make sure the timestamp field is different 
                                //even the time is identical.
				if(lastTime.compareAndSet(tempTime, ++tempTime)) {
					time = tempTime;
					break;
				}
			}
		}
		return time;
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值