标签:root this 数据集 命令 turn 单机 关注 雪花 速度
每一次HTTP请求,数据库的事务的执行,我们追踪代码执行的过程中,需要一个唯一值和这些业务操作相关联,对于单机的系统,可以用数据库的自增ID或者时间戳加一个在本机递增值,即可实现唯一值。但在分布式,又该如何实现唯一性的ID
1:第一个bit位(1bit):Java中long的最高位是符号位代表正负,正数是0,负数是1,一般生成ID都为正数,所以默认为0。
2:时间戳部分(41bit):毫秒级的时间,不建议存当前时间戳,而是用(当前时间戳 - 固定开始时间戳)的差值,可以使产生的ID从更小的值开始
3:工作机器id(10bit):也被叫做workId,这个可以灵活配置,机房或者机器号组合都可以。
4:序列号部分(12bit),自增值支持同一毫秒内同一个节点可以生成4096个ID
//Twitter的SnowFlake算法,使用SnowFlake算法生成一个整数 public class SnowFlakeShortUrl { //起始的时间戳 static long START_TIMESTAMP = 1624698370256L; //每一部分占用的位数 static long SEQUENCE_BIT = 12; //序列号占用的位数 static long MACHINE_BIT = 5; //机器标识占用的位数 static long DATA_CENTER_BIT = 5; //数据中心占用的位数 //每一部分的最大值 static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT); static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT); static long MAX_DATA_CENTER_NUM = -1L ^ (-1L << DATA_CENTER_BIT); //每一部分向左的位移 static long MACHINE_LEFT = SEQUENCE_BIT; static long DATA_CENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT; static long TIMESTAMP_LEFT = DATA_CENTER_LEFT + DATA_CENTER_BIT; //dataCenterId + machineId 等于10bit工作机器ID private long dataCenterId; //数据中心 private long machineId; //机器标识 private volatile long sequence = 0L; //序列号 private volatile long lastTimeStamp = -1L; //上一次时间戳 private volatile long l currTimeStamp = -1L; //当前时间戳 private long getNextMill() { long mill = System.currentTimeMillis(); while (mill <= lastTimeStamp) mill = System.currentTimeMillis(); return mill; } //根据指定的数据中心ID和机器标志ID生成指定的序列号 public SnowFlakeShortUrl(long dataCenterId, long machineId) { Assert.isTrue(dataCenterId >=0 && dataCenterId <= MAX_DATA_CENTER_NUM,"dataCenterId is illegal!"); Assert.isTrue(machineId >= 0 || machineId <= MAX_MACHINE_NUM,"machineId is illegal!"); this.dataCenterId = dataCenterId; this.machineId = machineId; } //生成下一个ID public synchronized long nextId() { currTimeStamp = System.currentTimeMillis(); Assert.isTrue(currTimeStamp >= lastTimeStamp,"Clock moved backwards"); if (currTimeStamp == lastTimeStamp) { //相同毫秒内,序列号自增 sequence = (sequence + 1) & MAX_SEQUENCE; if (sequence == 0L) { //同一毫秒的序列数已经达到最大,获取下一个毫秒 currTimeStamp = getNextMill(); } } else { sequence = 0L; //不同毫秒内,序列号置为0 } lastTimeStamp = currTimeStamp; return (currTimeStamp - START_TIMESTAMP) << TIMESTAMP_LEFT //时间戳部分 | dataCenterId << DATA_CENTER_LEFT //数据中心部分 | machineId << MACHINE_LEFT //机器标识部分 | sequence; //序列号部分 } public static void main(String[] args) { SnowFlakeShortUrl snowFlake = new SnowFlakeShortUrl(10, 4); for (int i = 0; i < (1 << 12); i++) { //10进制 System.out.println(snowFlake.nextId()); } } }
标签:root this 数据集 命令 turn 单机 关注 雪花 速度
原文地址:https://www.cnblogs.com/saintyear/p/14940337.html