分布式ID生成策略

简介

本文基于Twitter的分布式ID生成策略,并做了一定的改动,以适应业务需要。
分布式ID生成的关键点:

  1. 全局唯一性;
  2. 生成速度;
  3. ID 所表达的含义;
功能:

分布式ID生成服务

  • nextId() 新 ID ,线程安全
源码:

接口
/**
 * <p>Function: ID 生成服务. </p>
 * @author Dotions 2016年5月24日下午5:58:36
 */
public interface IdGenService {
    public long nextId() throws Exception;
}
实现类
import java.util.HashSet;
import java.util.Set;

/**
 * <p>
 * Function: Twitter 的 ID 生成策略.<br/>
 * 此实现中,简化了Twitter的生成策略。主要是取消了datacenter的标记,并将workerId值扩展到了1023。<br/>
 * </p>
 * 
 * @author Wang Yunfei 2016年5月24日下午6:00:31
 */
public class TwitterIdGenServiceImpl implements IdGenService {

    private long workerId;
    
    // 不用datacenter Id
//    private long datacenterId;
    
    private long sequence = 0L;

    private long twepoch = 1288834974657L; // 起始标记点,作为基准
    
//    private long workerIdBits = 5L;
//    private long datacenterIdBits = 5L;
    
    // 不需要datacenterId,只用workerId,扩展到10位
    private long workerIdBits = 10L; // 只允许workid的范围为:0-1023
    
    private long maxWorkerId = -1L ^ (-1L << workerIdBits);
    
//    private long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
    
    private long sequenceBits = 12L;
    private long workerIdShift = sequenceBits;
//    private long datacenterIdShift = sequenceBits + workerIdBits;
    
//    private long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
    
    private long timestampLeftShift = sequenceBits + workerIdBits;
    
    private long sequenceMask = -1L ^ (-1L << sequenceBits);
    private long lastTimestamp = -1L;
    
    public TwitterIdGenServiceImpl(long workerId) {
        super();
        
        // sanity check for workerId
        // 只允许workId的范围为:0-1023
        if (workerId > maxWorkerId || workerId < 0) {
            throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
        }
        this.workerId = workerId;
    }
    
    /**
     *  下一个ID
     * */
    public long synchronized nextId() throws Exception {
        
        long timestamp = timeGen();

        if (timestamp < lastTimestamp) {
            throw new Exception(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
        }

        if (lastTimestamp == timestamp) {
            sequence = (sequence + 1) & sequenceMask;
            if (sequence == 0) {
                timestamp = tilNextMillis(lastTimestamp);
            }
        } else {
            sequence = 0;
        }
        
        lastTimestamp = timestamp;
        
        return ((timestamp - twepoch) << timestampLeftShift) |
//                  (datacenterId << datacenterIdShift) |
                  (workerId << workerIdShift) | sequence;
    }

    /**
     * 保证返回的毫秒数在参数之后
     * 
     * @param lastTimestamp
     * @return
     */
    private static long tilNextMillis(long lastTimestamp) {
        long timestamp = timeGen();
        while (timestamp <= lastTimestamp) {
            timestamp = timeGen();
        }
        return timestamp;
    }

    /**
     * 获得系统当前毫秒数
     * 
     * @return
     */
    private static long timeGen() {
        return System.currentTimeMillis();
    }
    
}

用法:
public static void main(String[] args) {
        IdGenService idWorkder = new TwitterIdGenServiceImpl(0);
        try {
            
            Set<Long> set = new HashSet<Long>(100000);
            
            for (int i = 0; i < 10000000; i++) {
                set.add(idWorkder.nextId());
            }
            
            System.out.println(set.size());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 177,526评论 25 709
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 136,332评论 19 139
  • 冬天到了,叶子落了 天空灰蒙蒙的一整天了 不,是一段时间了 顺势随流蜷缩在墙角躲风 一个冬...
    凡人凡心阅读 347评论 0 0
  • 文章里 鲜有符号表达句子所带的情感停顿 为何 喜欢不羁文字 就像 所想的自己 不奢求 华丽 繁琐 只是平淡 简单 ...
    游鱼杂馆阅读 261评论 0 0
  • 小舒今天又来找我诉苦,说她真的蓝瘦,一脸香菇的表情,想到她往日的光辉日子,满脸的自信己荡然无存,明亮的双眸更是充满...
    超sun阅读 186评论 0 0

友情链接更多精彩内容