diff --git a/.gitignore b/.gitignore index 3ce5fb0..c5cbd26 100644 --- a/.gitignore +++ b/.gitignore @@ -259,4 +259,6 @@ target/ # macOS .DS_Store +# python +__pycache__ diff --git a/Python/README.md b/Python/README.md index ff9aec2..08a5883 100644 --- a/Python/README.md +++ b/Python/README.md @@ -7,6 +7,20 @@ Python 3.6+ ## 引用 包 - ## 调用示例 +```python +# 导入包 +from source import Options,Generator +# 声明id生成器参数,需要自己构建一个workerId +options = Options.IdGeneratorOptions(workerId=23) +# 参数中,WorkerIdBitLength 默认值6,支持的 WorkerId 最大值为2^6-1,若 WorkerId 超过64,可设置更大的 WorkerIdBitLength +idgen = Generator.DefaultIdGenerator() +# 保存参数 +idgen.SetIdGernerator(options) +# 生成id +uid = idgen.NextId() +# 打印出来查看 +print("%d, %x" % (uid,uid)) +``` + diff --git a/Python/source/DefaultIdGenerator.py b/Python/source/DefaultIdGenerator.py deleted file mode 100644 index 586e536..0000000 --- a/Python/source/DefaultIdGenerator.py +++ /dev/null @@ -1,31 +0,0 @@ -import time -import traceback -from IdGeneratorOptions import IdGeneratorOptions -from SnowFlake import SnowFlake -from SnowFlakeM1 import SnowFlakeM1 - -class DefaultIdGenerator(object): - - def SetIdGernerator(self, options) : - if options.BaseTime < 100000 : - raise ValueError ("BaseTime error.") - - self.SnowFlake= SnowFlakeM1(options) - - def NextId(self): - return self.SnowFlake.NextId() - -if __name__ == '__main__': - try: - options = IdGeneratorOptions(23) - options.BaseTime = 1231111111 - idgen = DefaultIdGenerator() - idgen.SetIdGernerator(options) - - print (idgen.NextId()) - print (options.__dict__) - - except ValueError as e: - print(e) - - diff --git a/Python/source/Generator.py b/Python/source/Generator.py new file mode 100644 index 0000000..92a3185 --- /dev/null +++ b/Python/source/Generator.py @@ -0,0 +1,17 @@ +from .Options import IdGeneratorOptions +from .SnowFlakeM1 import SnowFlakeM1 + +class DefaultIdGenerator(): + + def SetIdGernerator(self, options:IdGeneratorOptions) : + if options.BaseTime < 100000 : + raise ValueError ("BaseTime error.") + + self.SnowFlake= SnowFlakeM1(options) + + def NextId(self) -> int: + """ + 获取新的UUID + """ + return self.SnowFlake.NextId() + diff --git a/Python/source/IdGeneratorOptions.py b/Python/source/Options.py similarity index 96% rename from Python/source/IdGeneratorOptions.py rename to Python/source/Options.py index 2f4d2af..1c0ee07 100644 --- a/Python/source/IdGeneratorOptions.py +++ b/Python/source/Options.py @@ -1,6 +1,5 @@ -import time -class IdGeneratorOptions(object): +class IdGeneratorOptions(): def __init__(self, workerId = 0, workerIdBitLength = 6, seqBitLength = 6): # 雪花计算方法,(1-漂移算法|2-传统算法),默认1。目前只实现了1。 @@ -26,5 +25,3 @@ class IdGeneratorOptions(object): # 最大漂移次数(含),默认2000,推荐范围500-10000(与计算能力有关) self.TopOverCostCount = 2000 - - diff --git a/Python/source/SnowFlake.py b/Python/source/SnowFlake.py index cb603c8..0be3be0 100644 --- a/Python/source/SnowFlake.py +++ b/Python/source/SnowFlake.py @@ -7,5 +7,5 @@ class SnowFlake(object): def __init__(self, options): self.Options = options - def NextId(self): + def NextId(self) -> int: return 0 diff --git a/Python/source/SnowFlakeM1.py b/Python/source/SnowFlakeM1.py index 985bd08..d1fb467 100644 --- a/Python/source/SnowFlakeM1.py +++ b/Python/source/SnowFlakeM1.py @@ -1,12 +1,136 @@ #!/usr/bin/python # coding=UTF-8 -from SnowFlake import SnowFlake +from .SnowFlake import SnowFlake +from .Options import IdGeneratorOptions +import threading,time # 组件编号生成器 class SnowFlakeM1(SnowFlake): - def __init__(self, options): - self.Options = options + def __init__(self, options:IdGeneratorOptions): + # 1.BaseTime + if options.BaseTime != 0: + self.BaseTime = int(options.BaseTime) + else: + self.BaseTime = 1582136402000 - def NextId(self): - return self.Options.WorkerId + # 2.WorkerIdBitLength + if options.WorkerIdBitLength == 0: + self.WorkerIdBitLength = 6 + else: + self.WorkerIdBitLength = int(options.WorkerIdBitLength) + + # 3.WorkerId + self.WorkerId = options.WorkerId + + # 4.SeqBitLength + if options.SeqBitLength == 0: + self.SeqBitLength = 6 + else: + self.SeqBitLength = int(options.SeqBitLength) + + # 5.MaxSeqNumber + if options.MaxSeqNumber <= 0: + self.MaxSeqNumber = (1 << self.SeqBitLength) - 1 + else: + self.MaxSeqNumber = int(options.MaxSeqNumber) + + # 6.MinSeqNumber + self.MinSeqNumber = int(options.MinSeqNumber) + + # 7.TopOverCostCount + self.TopOverCostCount = int(options.TopOverCostCount) + + # 8.Others + self.__TimestampShift = self.WorkerIdBitLength + self.SeqBitLength + self.__CurrentSeqNumber = self.MinSeqNumber + self.__LastTimeTick:int = 0 + self.__TurnBackTimeTick:int = 0 + self.__TurnBackIndex:int = 0 + self.__IsOverCost = False + self.__OverCostCountInOneTerm:int = 0 + self.__IDLock = threading.Lock() + + def __NextOverCostId(self) -> int: + CurrentTimeTick = self.__GetCurrentTimeTick() + if CurrentTimeTick > self.__LastTimeTick: + self.__LastTimeTick = CurrentTimeTick + self.__CurrentSeqNumber = self.MinSeqNumber + self.__IsOverCost = False + self.__OverCostCountInOneTerm = 0 + return self.__CalcId(self.__LastTimeTick) + + if self.__OverCostCountInOneTerm >= self.TopOverCostCount: + self.__LastTimeTick = self.__GetNextTimeTick() + self.__CurrentSeqNumber = self.MinSeqNumber + self.__IsOverCost = False + self.__OverCostCountInOneTerm = 0 + return self.__CalcId(self.__LastTimeTick) + + if self.__CurrentSeqNumber > self.MaxSeqNumber: + self.__LastTimeTick+=1 + self.__CurrentSeqNumber = self.MinSeqNumber + self.__IsOverCost = True + self.__OverCostCountInOneTerm+=1 + return self.__CalcId(self.__LastTimeTick) + + return self.__CalcId(self.__LastTimeTick) + + def __NextNormalId(self) -> int: + CurrentTimeTick = self.__GetCurrentTimeTick() + if CurrentTimeTick < self.__LastTimeTick: + if self.__TurnBackTimeTick < 1: + self.__TurnBackTimeTick = self.__LastTimeTick - 1 + self.__TurnBackIndex+=1 + # 每毫秒序列数的前5位是预留位,0用于手工新值,1-4是时间回拨次序 + # 支持4次回拨次序(避免回拨重叠导致ID重复),可无限次回拨(次序循环使用)。 + if self.__TurnBackIndex > 4: + self.__TurnBackIndex = 1 + + return self.__CalcTurnBackId(self.__TurnBackTimeTick) + + # 时间追平时,_TurnBackTimeTick清零 + if self.__TurnBackTimeTick > 0: + self.__TurnBackTimeTick = 0 + + if CurrentTimeTick > self.__LastTimeTick: + self.__LastTimeTick = CurrentTimeTick + self.__CurrentSeqNumber = self.MinSeqNumber + return self.__CalcId(self.__LastTimeTick) + + if self.__CurrentSeqNumber > self.MaxSeqNumber: + self.__LastTimeTick+=1 + self.__CurrentSeqNumber = self.MinSeqNumber + self.__IsOverCost = True + self.__OverCostCountInOneTerm = 1 + return self.__CalcId(self.__LastTimeTick) + + return self.__CalcId(self.__LastTimeTick) + + def __CalcId(self,useTimeTick) -> int: + self.__CurrentSeqNumber+=1 + return ((useTimeTick< int: + self.__TurnBackTimeTick-=1 + return ((useTimeTick< int: + return int((time.time_ns() / 1e6) - self.BaseTime) + + def __GetNextTimeTick(self) -> int: + TempTimeTicker = self.__GetCurrentTimeTick() + while TempTimeTicker <= self.__LastTimeTick: + # 0.001 = 1 mili sec + time.sleep(0.001) + TempTimeTicker = self.__GetCurrentTimeTick() + return TempTimeTicker + + def NextId(self) -> int: + self.__IDLock.acquire() + if self.__IsOverCost: + id = self.__NextOverCostId() + else: + id = self.__NextNormalId() + self.__IDLock.release() + return id diff --git a/Python/test.py b/Python/test.py new file mode 100644 index 0000000..2662be5 --- /dev/null +++ b/Python/test.py @@ -0,0 +1,18 @@ +from source import Options,Generator + +if __name__ == '__main__': + try: + options = Options.IdGeneratorOptions(workerId=23,seqBitLength=10) + options.BaseTime = 1231111111 + idgen = Generator.DefaultIdGenerator() + idgen.SetIdGernerator(options) + + uid = idgen.NextId() + + print(uid) + print(options.__dict__) + + except ValueError as e: + print(e) + +