# 介绍
雪花算法是 twitter
开源的由 64
位整数组成的分布式 id
。目的是在分布式系统中产生全局唯一且趋势递增的 ID
。
其核心思想就是:使用一个 64 bit
的 long
型的数字作为全局唯一 id
。在分布式系统中的应用十分广泛,且 ID
引入了时间戳,保持自增性且不重复。
# 雪花算法的结构
标识: 没有实际意义。一般都是 0,都是正数。
时间戳: 41 bit
可以表示的数字多达 2^41 - 1
,也就是可以标识 2 ^ 41 - 1
个毫秒值,换算成年就是表示 69
年的时间。
机器 id: 这里标识的是机器的唯一标识,一般由两部分构成: 机房id+机器id
。一共 10
位,可以表示 1024
台机器。
序列号:可以用这个 12 bit
代表的数字来区分同一个毫秒内的 4096
个不同的 id
。也就是同一毫秒内同一台机器所生成的最大 ID 数量为 4096
# 雪花算法的工作流程
以一个简单的雪花算法工作流程来说。假设有一个服务假设要生成一个全局唯一 id
,那么就可以发送一个请求给部署了 SnowFlake
算法的系统,由这个 SnowFlake
算法系统来生成唯一 id
。这个 SnowFlake
算法系统首先肯定是知道自己所在的机器号,(假设机器 id 为 10bit)接着 SnowFlake
算法系统接收到这个请求之后,首先就会用二进制位运算的方式生成一个 64 bit
的 long
型 id
, 64
个 bit
中的第一个 bit
是无意义的。接着用当前时间戳(单位到毫秒)占用 41
个 bit
,然后接着 10
个 bit
设置机器 id
。最后再判断一下,当前这台机房的这台机器上这一毫秒内,这是第几个请求,给这次生成 id
的请求累加一个序号,作为最后的 12
个 bit
。
# 雪花算法实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 package com.fxb.algorithm;public class SnowFlakeGenerator { private final static long DEFAULT_TIMESTAMP = 1603556068000L ; private final static long BITS_COUNT = 64L ; private final static long DEFAULT_WORKER_ID_BITS = 5L ; private final static long DEFAULT_DATA_CENTER_ID_BITS = 5L ; private final static long DEFAULT_SEQUENCE_BITS = 12L ; private final static long DEFAULT_MAX_WORKER_ID = ~(-1L << DEFAULT_WORKER_ID_BITS); private final static long DEFAULT_MAX_DATA_CENTER_ID_BITS = ~(-1L << DEFAULT_DATA_CENTER_ID_BITS); private final static long DEFAULT_SEQUENCE_MASK = ~(-1L << DEFAULT_SEQUENCE_BITS); private final static long DEFAULT_TIMESTAMP_LEFT_SHIFT = DEFAULT_SEQUENCE_BITS + DEFAULT_WORKER_ID_BITS + DEFAULT_DATA_CENTER_ID_BITS; private final static long DEFAULT_DATA_CENTER_ID_SHIFT = DEFAULT_SEQUENCE_BITS + DEFAULT_WORKER_ID_BITS; private final static long DEFAULT_WORKER_ID_SHIFT = DEFAULT_SEQUENCE_BITS; private long workerId; private long dataCenterId; private long maxDataCenterId; private long maxWorkerId; private Long sequenceBits; private Long sequenceMask; private long sequence = 0L ; private long lastTimestamp = -1L ; private long dataCenterIdShift; private long workerIdShift; private long timestampLeftShift; public SnowFlakeGenerator (long workerId, long dataCenterId) { } public SnowFlakeGenerator (long workerId, long dataCenterId, long workerIdBits, long dataCenterIdBits) { } public synchronized long nextId () { long currentTimestamp = getCurrentTimeStamp(); if (currentTimestamp < lastTimestamp) { throw new RuntimeException( String.format("Clock moved backwards. Refusing to generate id for %d milliseconds" , lastTimestamp - currentTimestamp)); } if (lastTimestamp == currentTimestamp) { sequence = (sequence + 1 ) & sequenceMask; if (sequence == 0 ) { currentTimestamp = tilNextMillis(lastTimestamp); } } else { sequence = 0L ; } lastTimestamp = currentTimestamp; return ((currentTimestamp - DEFAULT_TIMESTAMP) << timestampLeftShift) | (dataCenterId << dataCenterIdShift) | (workerId << workerIdShift) | sequence; } protected long tilNextMillis (long lastTimestamp) { long timestamp = getCurrentTimeStamp(); while (timestamp <= lastTimestamp) { timestamp = getCurrentTimeStamp(); } return timestamp; } private long getCurrentTimeStamp () { return System.currentTimeMillis(); } }
完整代码: http://dwz.date/cWmR
公众号中回复 【雪花算法】,可以直接获取源码文件。
# 最后
期望与你一起遇见更好的自己
扫码或搜索:方家小白
发送 290992
即可立即永久 解锁本站全部文章