You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

snowflake_m1.py 5.5 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. """
  2. M1生成器
  3. """
  4. # !/usr/bin/python
  5. # coding=UTF-8
  6. import threading
  7. import time
  8. from .snowflake import SnowFlake
  9. from .options import IdGeneratorOptions
  10. class SnowFlakeM1(SnowFlake):
  11. """
  12. M1规则ID生成器配置
  13. """
  14. def __init__(self, options: IdGeneratorOptions):
  15. # 1.base_time
  16. self.base_time = 1582136402000
  17. if options.base_time != 0:
  18. self.base_time = int(options.base_time)
  19. # 2.worker_id_bit_length
  20. self.worker_id_bit_length = 6
  21. if options.worker_id_bit_length != 0:
  22. self.worker_id_bit_length = int(options.worker_id_bit_length)
  23. # 3.worker_id
  24. self.worker_id = options.worker_id
  25. # 4.seq_bit_length
  26. self.seq_bit_length = 6
  27. if options.seq_bit_length != 0:
  28. self.seq_bit_length = int(options.seq_bit_length)
  29. # 5.max_seq_number
  30. self.max_seq_number = int(options.max_seq_number)
  31. if options.max_seq_number <= 0:
  32. self.max_seq_number = (1 << self.seq_bit_length) - 1
  33. # 6.min_seq_number
  34. self.min_seq_number = int(options.min_seq_number)
  35. # 7.top_over_cost_count
  36. self.top_over_cost_count = int(options.top_over_cost_count)
  37. # 8.Others
  38. self.__timestamp_shift = self.worker_id_bit_length + self.seq_bit_length
  39. self.__current_seq_number = self.min_seq_number
  40. self.__last_time_tick: int = 0
  41. self.__turn_back_time_tick: int = 0
  42. self.__turn_back_index: int = 0
  43. self.__is_over_cost = False
  44. self.___over_cost_count_in_one_term: int = 0
  45. self.__id_lock = threading.Lock()
  46. def __next_over_cost_id(self) -> int:
  47. current_time_tick = self.__get_current_time_tick()
  48. if current_time_tick > self.__last_time_tick:
  49. self.__last_time_tick = current_time_tick
  50. self.__current_seq_number = self.min_seq_number
  51. self.__is_over_cost = False
  52. self.___over_cost_count_in_one_term = 0
  53. return self.__calc_id(self.__last_time_tick)
  54. if self.___over_cost_count_in_one_term >= self.top_over_cost_count:
  55. self.__last_time_tick = self.__get_next_time_tick()
  56. self.__current_seq_number = self.min_seq_number
  57. self.__is_over_cost = False
  58. self.___over_cost_count_in_one_term = 0
  59. return self.__calc_id(self.__last_time_tick)
  60. if self.__current_seq_number > self.max_seq_number:
  61. self.__last_time_tick += 1
  62. self.__current_seq_number = self.min_seq_number
  63. self.__is_over_cost = True
  64. self.___over_cost_count_in_one_term += 1
  65. return self.__calc_id(self.__last_time_tick)
  66. return self.__calc_id(self.__last_time_tick)
  67. def __next_normal_id(self) -> int:
  68. current_time_tick = self.__get_current_time_tick()
  69. if current_time_tick < self.__last_time_tick:
  70. if self.__turn_back_time_tick < 1:
  71. self.__turn_back_time_tick = self.__last_time_tick - 1
  72. self.__turn_back_index += 1
  73. # 每毫秒序列数的前5位是预留位, 0用于手工新值, 1-4是时间回拨次序
  74. # 支持4次回拨次序(避免回拨重叠导致ID重复), 可无限次回拨(次序循环使用)。
  75. if self.__turn_back_index > 4:
  76. self.__turn_back_index = 1
  77. return self.__calc_turn_back_id(self.__turn_back_time_tick)
  78. # 时间追平时, _TurnBackTimeTick清零
  79. self.__turn_back_time_tick = min(self.__turn_back_time_tick, 0)
  80. if current_time_tick > self.__last_time_tick:
  81. self.__last_time_tick = current_time_tick
  82. self.__current_seq_number = self.min_seq_number
  83. return self.__calc_id(self.__last_time_tick)
  84. if self.__current_seq_number > self.max_seq_number:
  85. self.__last_time_tick += 1
  86. self.__current_seq_number = self.min_seq_number
  87. self.__is_over_cost = True
  88. self.___over_cost_count_in_one_term = 1
  89. return self.__calc_id(self.__last_time_tick)
  90. return self.__calc_id(self.__last_time_tick)
  91. def __calc_id(self, use_time_tick) -> int:
  92. self.__current_seq_number += 1
  93. return (
  94. (use_time_tick << self.__timestamp_shift) +
  95. (self.worker_id << self.seq_bit_length) +
  96. self.__current_seq_number
  97. ) % int(1e64)
  98. def __calc_turn_back_id(self, use_time_tick) -> int:
  99. self.__turn_back_time_tick -= 1
  100. return (
  101. (use_time_tick << self.__timestamp_shift) +
  102. (self.worker_id << self.seq_bit_length) +
  103. self.__turn_back_index
  104. ) % int(1e64)
  105. def __get_current_time_tick(self) -> int:
  106. return int((time.time_ns() / 1e6) - self.base_time)
  107. def __get_next_time_tick(self) -> int:
  108. temp_time_ticker = self.__get_current_time_tick()
  109. while temp_time_ticker <= self.__last_time_tick:
  110. # 0.001 = 1 mili sec
  111. time.sleep(0.001)
  112. temp_time_ticker = self.__get_current_time_tick()
  113. return temp_time_ticker
  114. def next_id(self) -> int:
  115. with self.__id_lock:
  116. if self.__is_over_cost:
  117. nextid = self.__next_over_cost_id()
  118. else:
  119. nextid = self.__next_normal_id()
  120. return nextid