参考文章:https://www.cnblogs.com/oklizz/p/11865750.html
雪花算法(Snowflake)是一种分布式唯一ID生成算法,它可以生成全局唯一、趋势递增的64位ID。该算法最初由Twitter公司开发,用于生成Twitter的全局唯一ID。
核心的目的:分布式系统中全局唯一ID的生成
生成的逻辑:
1 bit:一般是符号位,不做处理。
41bit : 用来记录时间戳,这里可以记录69年,如果设置好起始时间,比如今年是 2022 ,那么可以用到 2091 年,到时候怎么办,这个系统要是能够使用 69 年,估计系统早已经优化过很多次了。
10bit : 用来记录机器ID,总共可以记录1024台机器,一般用前5位代表数据中心,后面5位是某个数据中心的机器ID。(注:位数可以根据情况进行设定。)
12bit:循环用来对同一个毫秒内产生的不同的 ID,12位可以最多记录4095(212-1)次,多余的需要在下一毫秒进行处理。
生成的作用:
雪花算法的作用和意义在于,为分布式系统中的各种数据对象(如消息、事件、日志等)生成全局唯一的ID。这些ID可以通过时间戳的方式粗略地保证唯一性,同时也可以通过特定的位数来指定不同的业务类型。这样一来,不同节点之间就可以无需协调地生成全局唯一ID,从而提高系统的扩展性、并行性以及可靠性。
雪花算法在分布式系统中的应用场景。
分析雪花算法在提高系统扩展、并行性和可靠性方面的作用和意义。
展示实际应用举例,如Twitter等公司如何利用雪花算法生成唯一ID。
高效:雪花算法使用简单,计算速度快,可以轻松地嵌入到各种语言和框架中,支持高并发场景下的ID生成。
全局唯一:雪花算法生成的ID是全局唯一的,不需要复杂的协调机制,可以方便地应用于分布式系统中。
趋势递增:雪花算法生成的ID按照时间戳递增排序,方便对数据进行排序和查询。
可配置性:雪花算法支持根据需求自定义位数,可以支持多种应用场景。
依赖于系统时钟:雪花算法的ID生成依赖于系统时钟,如果系统时钟回拨或者发生调整,可能会导致生成的ID不唯一或趋势逆序。
可读性差:由于雪花算法生成的ID是64位的数字,对人类来说比较难以理解和记忆。
总体来说,雪花算法是一种简单、高效、可扩展的分布式唯一ID生成算法,在分布式系统中广泛应用。但是需要注意的是,在使用时要注意系统时钟同步以及生成的ID长度适当。
#!/usr/bin/env/python3
# -*- coding:utf-8 -*-
import time
import logging
# from exceptions import InvalidSystemClock # 继承的Excpetion即可。
# 64 位 id 的划分,通常机器位和数据位各为 5 位
WORKER_ID_BITS = 5 # 机器位
DATACENTER_ID_BITS = 5 # 数据位
SEQUENCE_BITS = 12 # 循环位
# 最大取值计算,计算机中负数表示为他的补码
MAX_WORKER_ID = -1^(-1 << WORKER_ID_BITS) # 2**5 -1 =31
MAX_DATACENTER_ID = -1 ^(-1 << DATACENTER_ID_BITS)
# 移位偏移计算
WORKER_ID_SHIFT = SEQUENCE_BITS
DATACENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS
TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATACENTER_ID_BITS
# X序号循环掩码
SEQUENCE_MASK = -1^(-1 << SEQUENCE_BITS)
# Twitter 元年时间戳
TWEPOCH = 1288834974657
logger = logging.getLogger('雪花算法')
class IdWorker(object):
'''
用于生成IDS.
'''
def __init__(self,datacenter_id,worker_id,sequence=0):
'''
初始化方法
:param datacenter_id:数据id
:param worker_id:机器id
:param sequence:序列码
'''
if worker_id > MAX_WORKER_ID or worker_id <0:
raise ValueError('worker_id 值越界')
if datacenter_id >MAX_DATACENTER_ID or datacenter_id < 0:
raise ValueError('datacenter_id 值越界')
self.worker_id = worker_id
self.datacenter_id = datacenter_id
self.sequence = sequence
self.last_timestamp = -1 # 上次计算的时间戳
def _gen_timestamp(self):
'''
生成整数时间戳。
:return:
'''
return int(time.time()*1000)
def get_id(self):
'''
获取新的ID.
:return:
'''
# 获取当前时间戳
timestamp = self._gen_timestamp()
# 时钟回拨的情况
if timestamp < self.last_timestamp:
logging.error('clock is moving backwards. Rejecting requests util {}'.format(self.last_timestamp))
# raise InvalidSystemClock
if timestamp == self.last_timestamp:
# 同一毫秒的处理。
self.sequence = (self.sequence+1) & SEQUENCE_MASK
if self.sequence == 0:
timestamp =self._til_next_millis(self.last_timestamp)
else:
self.sequence = 0
self.last_timestamp =timestamp
new_id = (((timestamp - TWEPOCH) << TIMESTAMP_LEFT_SHIFT)|(self.datacenter_id << DATACENTER_ID_SHIFT)|(self.worker_id << WORKER_ID_SHIFT))|self.sequence
return new_id
def _til_next_millis(self,last_timestamp):
'''
等到下一毫秒。
:param last_timestamp:
:return:
'''
timestamp = self._gen_timestamp()
while timestamp <= last_timestamp:
timestamp = self._gen_timestamp()
return timestamp
if __name__ == '__main__':
# worker = IdWorker(1,2,0)
# print(worker.get_id())
class lib_snowflake():
def __init__(self):
pass
def create_id(self):
# pip install pysnowflake
# cmd启动服务:snowflake_start_server --worker=1
from snowflake import client
print(client.get_guid())
if __name__ == '__main__':
lib_snowflake().create_id()
返回结果:
1641686872889630720
进程已结束,退出代码0