generator.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. # """
  2. # Snowflake ID 生成器,适配三台 MySQL 服务器(IP 尾号 251/252/253)。
  3. # """
  4. # import os
  5. # import socket
  6. # import threading
  7. # import time
  8. # import warnings
  9. # from typing import Dict, Optional
  10. #
  11. # # Snowflake 位分配:41-bit 时间戳 | 5-bit 机房 | 5-bit 节点 | 12-bit 自增序列
  12. # EPOCH_MS = 1704067200000 # 2024-01-01 00:00:00 UTC
  13. # WORKER_ID_BITS = 5
  14. # DATACENTER_ID_BITS = 5
  15. # SEQUENCE_BITS = 12
  16. #
  17. # MAX_WORKER_ID = (1 << WORKER_ID_BITS) - 1
  18. # MAX_DATACENTER_ID = (1 << DATACENTER_ID_BITS) - 1
  19. # SEQUENCE_MASK = (1 << SEQUENCE_BITS) - 1
  20. #
  21. # WORKER_SHIFT = SEQUENCE_BITS
  22. # DATACENTER_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS
  23. # TIMESTAMP_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATACENTER_ID_BITS
  24. #
  25. # # 默认映射:将三台 MySQL 服务器 IP(或尾段)映射到 worker_id
  26. # # DEFAULT_IP_WORKER_MAP: Dict[str, int] = {
  27. # # "251": 1,
  28. # # "252": 2,
  29. # # "253": 3,
  30. # # }
  31. #
  32. #
  33. # # 单机
  34. # DEFAULT_IP_WORKER_MAP: Dict[str, int] = {
  35. # "168": 1,
  36. # }
  37. #
  38. #
  39. # def _now_ms() -> int:
  40. # return int(time.time() * 1000)
  41. #
  42. #
  43. # def _wait_next_ms(last_ts: int) -> int:
  44. # ts = _now_ms()
  45. # while ts <= last_ts:
  46. # ts = _now_ms()
  47. # return ts
  48. #
  49. #
  50. # def _get_host_ip() -> str:
  51. # """获取当前主机的主 IP 地址。"""
  52. # s = None
  53. # try:
  54. # s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  55. # # 连接一个无需真实可达的地址,只为获取本机出站 IP
  56. # s.connect(("10.255.255.255", 1))
  57. # ip = s.getsockname()[0]
  58. # except Exception:
  59. # ip = socket.gethostbyname(socket.gethostname())
  60. # finally:
  61. # if s is not None:
  62. # s.close()
  63. # return ip
  64. #
  65. #
  66. # def resolve_worker_id(
  67. # ip_worker_map: Optional[Dict[str, int]] = None,
  68. # override_ip: Optional[str] = None,
  69. # ) -> int:
  70. # """
  71. # 根据主机 IP 推导 worker_id。
  72. # - 优先读取环境变量 SNOWFLAKE_WORKER_IP 作为 IP。
  73. # - 其次使用 override_ip。
  74. # - 再次使用本机 IP。
  75. # - 支持完整 IP 匹配和末段匹配(如 "192.168.0.251" 或 "251")。
  76. # """
  77. # ip_worker_map = ip_worker_map or DEFAULT_IP_WORKER_MAP
  78. # chosen_ip = os.getenv("SNOWFLAKE_WORKER_IP") or override_ip or _get_host_ip()
  79. # if chosen_ip in ip_worker_map:
  80. # return ip_worker_map[chosen_ip]
  81. # last_octet = chosen_ip.split(".")[-1]
  82. # if last_octet in ip_worker_map:
  83. # return ip_worker_map[last_octet]
  84. # raise ValueError(
  85. # f"未能为 IP {chosen_ip} 匹配到 worker_id,请检查映射或设置 SNOWFLAKE_WORKER_IP。"
  86. # )
  87. #
  88. #
  89. # class SnowflakeGenerator:
  90. # """
  91. # 线程安全的 Snowflake ID 生成器。
  92. # 默认 datacenter_id=0;worker_id 将根据 IP 映射推导。
  93. # """
  94. #
  95. # def __init__(
  96. # self,
  97. # datacenter_id: int = 0,
  98. # worker_id: Optional[int] = None,
  99. # epoch_ms: int = EPOCH_MS,
  100. # ip_worker_map: Optional[Dict[str, int]] = None,
  101. # ):
  102. # self.datacenter_id = datacenter_id
  103. # self.worker_id = worker_id or resolve_worker_id(ip_worker_map)
  104. # self.epoch_ms = epoch_ms
  105. #
  106. # if not 0 <= self.worker_id <= MAX_WORKER_ID:
  107. # raise ValueError(f"worker_id 必须在 0-{MAX_WORKER_ID} 之间")
  108. # if not 0 <= self.datacenter_id <= MAX_DATACENTER_ID:
  109. # raise ValueError(f"datacenter_id 必须在 0-{MAX_DATACENTER_ID} 之间")
  110. #
  111. # self.sequence = 0
  112. # self.last_timestamp = -1
  113. # self._lock = threading.Lock()
  114. #
  115. # def next_id(self) -> int:
  116. # """生成下一个全局唯一 ID。"""
  117. # with self._lock:
  118. # timestamp = _now_ms()
  119. #
  120. # if timestamp < self.last_timestamp:
  121. # # 时钟回拨保护
  122. # raise RuntimeError("检测到系统时钟回拨,停止发号。")
  123. #
  124. # if timestamp == self.last_timestamp:
  125. # self.sequence = (self.sequence + 1) & SEQUENCE_MASK
  126. # if self.sequence == 0:
  127. # timestamp = _wait_next_ms(self.last_timestamp)
  128. # else:
  129. # self.sequence = 0
  130. #
  131. # self.last_timestamp = timestamp
  132. # return (
  133. # ((timestamp - self.epoch_ms) << TIMESTAMP_SHIFT)
  134. # | (self.datacenter_id << DATACENTER_SHIFT)
  135. # | (self.worker_id << WORKER_SHIFT)
  136. # | self.sequence
  137. # )
  138. #
  139. #
  140. # # 默认生成器:datacenter_id=0,worker_id 按 IP 映射自动推导
  141. # def _build_default_generator() -> SnowflakeGenerator:
  142. # try:
  143. # return SnowflakeGenerator()
  144. # except ValueError as exc:
  145. # warnings.warn(
  146. # f"Snowflake 默认生成器未找到匹配的 IP,退回 worker_id=0。详情:{exc}",
  147. # RuntimeWarning,
  148. # )
  149. # return SnowflakeGenerator(worker_id=0)
  150. #
  151. #
  152. # default_generator = _build_default_generator()
  153. #
  154. #
  155. # def next_id() -> int:
  156. # """便捷函数,返回默认生成器的下一个 ID。"""
  157. # return default_generator.next_id()
  158. #
  159. #
  160. #