基于雪花算法生成64位ID
import logging
import time
class Generator(object):
"""
64位ID 1(符号位不用) (41(毫秒)+4(机器ID)+6(业务编码)+12(重复累加))
基础时间(毫秒): 1577808000000 2020/01/01/ 00:00
最大支持时间差: 2199023255551(0x1ffffffffffbit) 基于毫秒算大约可用69年(2199023255551/1000/60/60/24/365.25)
dc: 4bit (自动取值范围[0,16))
worker: 6bit (自动取值范围[0,64))
desc: 同一时刻产生4095个id,原理上支持每秒409.5万个id,由于执行效率问题,本程序经测试每秒约能产生70万个id
"""
EPOCH_TIMESTAMP = 1577808000000
MAX_SEQUENCE = 4095
def __init__(self, dc, worker):
self.dc = dc
self.worker = worker
self.node_id = ((dc & 0xf) << 6) | (worker & 0x3f)
self.last_timestamp = self.EPOCH_TIMESTAMP
self.sequence = 0
self.sequence_overload = 0
self.errors = 0
self.generated_ids = 0
def get_next_id(self):
""" id生产
"""
curr_time = int(time.time() * 1000)
if curr_time < self.last_timestamp:
self.errors += 1
raise Exception('Clock went backwards! %d < %d' % (curr_time, self.last_timestamp))
if curr_time > self.last_timestamp:
self.sequence = 0
self.last_timestamp = curr_time
self.sequence += 1
if self.sequence > self.MAX_SEQUENCE:
logging.warning('The sequence has been overload')
self.sequence_overload += 1
time.sleep(0.001)
return self.get_next_id()
diff_time = curr_time - self.EPOCH_TIMESTAMP
generated_id = ((diff_time & 0x1ffffffffff) << 22) | (self.node_id << 12) | self.sequence
self.generated_ids += 1
return generated_id
@property
def stats(self):
""" 状态查询
"""
return {
'dc': self.dc,
'worker': self.worker,
'timestamp': int(time.time() * 1000),
'last_timestamp': self.last_timestamp,
'sequence': self.sequence,
'sequence_overload': self.sequence_overload,
'errors': self.errors,
}
def pressure_test(self):
""" 压力测试
"""
start_time = int(time.time() * 1000)
end_time = 1000 + start_time
id_num = 0
while self.last_timestamp <= end_time:
self.get_next_id()
id_num += 1
print(id_num)
if __name__ == '__main__':
a = Generator(0, 0)
a.pressure_test()