#coding:utf-8
'''
create on 2020-11-23
@author:sandy
'''
import time
class SnowFlake(object):
def __init__(self,datacenterId,machineId):
self.sequence = 0
self.laststmp = -1
self.sequence_bit = 12
self.machine_bit = 5
self.datacenter_bit = 5
self.max_datacenter_num = -1 ^ (-1 << self.datacenter_bit)
self.max_machine_num = -1 ^ (-1 << self.machine_bit)
self.max_sequence_num = -1 ^ (-1 << self.sequence_bit)
self.machine_left = self.sequence_bit
self.datacenter_left = self.sequence_bit + self.machine_bit
self.timestmp_left = self.datacenter_left + self.datacenter_bit
print(self.max_datacenter_num,self.max_machine_num,self.max_sequence_num)
if datacenterId > self.max_datacenter_num or datacenterId < 0:
raise Exception("datacenterId",datacenterId)
if machineId > self.max_machine_num or machineId < 0:
raise Exception("machineId",machineId)
self.start_stmp = 1606118422000L
self.datacenterId = datacenterId
self.machineId = machineId
def nextId(self):
curstmp = self.getNewStmp()
if curstmp < self.laststmp:
raise Exception("Clock moved backwards. Refusing to generate id")
if curstmp == self.laststmp:
self.sequence = (self.sequence + 1) & self.max_sequence_num
if self.sequence == 0:
time.sleep(0.001)
curstmp = self.getNewStmp()
else:
pass
else:
self.sequence = 0
self.laststmp = curstmp
ret = (curstmp - self.start_stmp) << self.timestmp_left | self.datacenterId << self.datacenter_left | self.machineId << self.machine_left | self.sequence
return ret
def getNewStmp(self):
return int(time.time() * 1000)
if __name__ == '__main__':
flake = SnowFlake(5,5)
for i in range(1000):
nextid = flake.nextId()
print(nextid)
snowflake的结构如下(每部分用-分开):
0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 第一位为未使用,
接下来的41位为毫秒级时间(41位的长度可以使用69年),
然后是5位datacenterId和5位workerId(10位的长度最多支持部署1024个节点)
最后12位是毫秒内的计数(12位的计数顺序号支持每个节点每毫秒产生4096个ID序号)
如果1ms内生成的数超过4096个 也就是self.sequence = (self.sequence + 1) & self.max_sequence_num 后 self.sequence == 0 这种情况,对于碰到这种情况 sleep 一下 当然也有其他的方式解决这种情况