仿照了网上仿照twitter的snowflake算法的例子,不是套娃 :)
自己简单测试了一下,没有出现重复的ID,缺点是用了两次随机数,长度实在是有点长,快赶上uuid了。
import time
import random
import threading
class SnowFlakeLite:
def __init__(self):
t = time.mktime(time.strptime('2015-01-01 00:00:00', "%Y-%m-%d %H:%M:%S"))
self.start = int(round(t * 1000))
self.last = int(round(time.time() * 1000))
self._incr_id = 1
def get_id(self):
"""
生成一个相对不重复的ID:[时间戳(毫秒)]+[随机数(1000~9999)]+[随机数(1000~9999)]+[000~999],例:2097354797114061735300067
"""
now = int(round(time.time() * 1000))
temp = now - self.start # 时间差
if now == self.last:
self._incr_id += 1 # 同一时间差,序列号自增
else:
self._incr_id = 0 # 不同时间差,序列号重新置为1
self.last = now
incr_id_str = str(self._incr_id)
length = len(incr_id_str)
if length < 5: # 序列号不够5位的在前面补0
s = "0" * (5 - length)
incr_id_str = s + incr_id_str
id_str = str(temp) + str(random.randint(1000, 9999)) + str(random.randint(1000, 9999)) + incr_id_str
return id_str
class MyThread(threading.Thread):
def __init__(self, thread_id, name, s):
threading.Thread.__init__(self)
self.thread_id = thread_id
self.name = name
self.snow_id = SnowFlakeLite()
self.s = s
def run(self):
#print("开启线程:" + self.name)
process_data(self.name, self.snow_id, self.s)
#print("退出线程:" + self.name)
def process_data(threadName, snow_id, s: list):
for i in range(10000):
s.append(snow_id.get_id())
def test1():
for i in range(50):
print("Round_{}:".format(i))
snow_id_list = list()
threads = []
for i in range(100):
thread = MyThread(i, "thread-{}".format(i), snow_id_list)
thread.start()
threads.append(thread)
#time.sleep(0.001)
for t in threads:
t.join()
print("snow_id_list total:{}".format(len(snow_id_list)))
snow_id_set = set(snow_id_list)
print("snow_id_list real total:{}".format(len(snow_id_set)))
# for i in snow_id_set:
# count = snow_id_list.count(i)
# if count > 1:
# print("{}.count:{}".format(str(i), count))
def test2():
s = SnowFlakeLite()
for i in range(200):
print(s.get_id())
#time.sleep(0.02)
if __name__ == '__main__':
#test1()
test2()