电子商务网站怎么备案,东莞市建设质量监督站,网站做跳转影响排名吗,wordpress 修改页面#x1f4eb; 作者简介#xff1a;「六月暴雪飞梨花」#xff0c;专注于研究Java#xff0c;就职于科技型公司后端工程师 #x1f3c6; 近期荣誉#xff1a;华为云云享专家、阿里云专家博主、 #x1f525; 三连支持#xff1a;欢迎 ❤️关注、#x1f44d;点赞、 作者简介「六月暴雪飞梨花」专注于研究Java就职于科技型公司后端工程师 近期荣誉华为云云享专家、阿里云专家博主、 三连支持欢迎 ❤️关注、点赞、收藏三连支持一下博主~ 文章目录 概述什么是雪花ID代码演示步骤1 引入依赖库2 初始化参数3 定义并实现4 测试代码5 异常处理 完整代码示例运行结果演示问题分析(1)第一位为什么不使用(2)机器位怎么用(3)时间戳比较 结束语 概述
分布式策略ID的主要应用在互联网网站、搜索引擎、社交媒体、在线购物、金融、大数据处理、日志场景中这些应用需要支持大量的并发请求和用户访问分布式ID策略可以通过请求分发到不同的服务器节点来做计算以提高服务的响应速度和可用性。 常见的分布式ID生成策略 ● UUIDUniversally Unique Identifier ● 雪花算法Snowflake ● Redis原子自增 ● 基于数据库的自增主键有些数据库不支持自增主键 ● 取当前毫秒数 本文主要简单介绍下雪花ID算法Snowflake的Python语言的计算方法。
雪花算法Snowflake是 Twitter 开源的分布式ID生成算法。雪花ID或称雪花是分布式计算中使用的唯一标识符的一种形式。该格式由Twitter创建用于推文的ID。人们普遍认为每片雪花都有唯一的结构因此他们取了“雪花ID”这个名字。在当时Twitter的团队从MySQL转向Cassandra时需要一种新的方法来生成ID号而Cassandra中没有顺序ID生成工具所以应运而生雪花ID出现了。
雪花算法的相关知识可以参考Githubhttps://github.com/twitter-archive/snowflake/tree/b3f6a3c6ca8e1b6847baa6ff42bf72201e2c2231
什么是雪花ID
根据官方的介绍雪花ID是由Twitter团队开发的一种分布式ID生成算法它的设计目标是在分布式系统中生成唯一ID具备趋势递增、高性能、可扩展等特点。其实雪花ID生成的唯一ID是由64位二进制数组成结果是一个long型的ID。可以分解为四个部分 ● 1 符号位符号位也就是最高位始终是0没有任何意义因为要是唯一计算机二进制补码中就是负数0才是正数。 ● 2 时间戳占用41位记录生成ID的时间戳精确到毫秒级。 ● 3 机器标识占用10位用于标识不同的机器。 ● 4 计数序列号占用12位用于解决同一毫秒内生成多个ID的冲突。 Snowflake ID的结构可以用二进制格式表示如下
0 1 41 51 64
----------------------------------------------------------
|0|timestamp (milliseconds since epoch) |worker| sequence |
----------------------------------------------------------Snowflake ID的结构可以用图表示如下
代码演示步骤
1 引入依赖库
使用Python标准库中的time模块来获取当前时间戳并使用random模块来生成随机worker_id和data_center_id。
import time
import random 2 初始化参数
此处我们定义一个类Snowflake类提前初始化机器标识ID、数据中心ID、计数序列号、时间戳。 def __init__(self, worker_id, data_center_id): ### 机器标识IDself.worker_id worker_id ### 数据中心IDself.data_center_id data_center_id ### 计数序列号self.sequence 0 ### 时间戳self.last_timestamp -1 3 定义并实现
这是最重要的一个步骤我们来实现一个生成ID的方法这个方法根据雪花算法的规则生成唯一ID具体的实现过程包括获取当前时间戳、判断是否为同一毫秒、更新序列号等。在next_id()方法中我们首先获取当前时间戳并检查是否比上一次生成ID的时间戳小。 1如果是则抛出异常因为这表示时钟回退。 2如果时间戳相同则递增序列号如果序列号达到最大值4095则等待下一毫秒。如果时间戳不同则重置序列号为0。 3最后我们将生成的ID返回。 具体代码如下所示 def next_id(self): timestamp int(time.time() * 1000) if timestamp self.last_timestamp: raise Exception(Clock moved backwards. Refusing to generate id for %d milliseconds % abs(timestamp - self.last_timestamp)) if timestamp self.last_timestamp: self.sequence (self.sequence 1) 4095 if self.sequence 0: timestamp self.wait_for_next_millis(self.last_timestamp) else: self.sequence 0 self.last_timestamp timestamp return ((timestamp - 1288834974657) 22) | (self.data_center_id 17) | (self.worker_id 12) | self.sequence 注意⚠️由于时间戳是以毫秒为单位的所以每毫秒最多可以生成4096个ID。如果ID生成器的负载较高可能会在同一毫秒内多次调用next_id()方法导致序列号耗尽。为了避免这种情况我们在等待下一毫秒时检查时间戳是否小于上一次生成ID的时间戳。如果是则抛出异常因为这表示时钟回退。
4 测试代码
在测试代码中我们使用一个循环来生成10个唯一的ID并打印出来。如果时钟回退则会抛出一个异常并打印错误信息。
if __name__ __main__: worker_id 1 data_center_id 1 snowflake Snowflake(worker_id, data_center_id) for i in range(10): try: print(snowflake.next_id()) except Exception as e: print(Clock moved backwards:, e)5 异常处理
通过上面几步我们已经实现了雪花ID的核心代码工作但是为了确保算法的正确性和程序的严谨性我们需要处理错误和边界情况比如当同一毫秒内生成的ID超过序列号的最大值时需要等待下一毫秒再生成。具体代码如下所示 def wait_for_next_millis(self, last_timestamp): timestamp int(time.time() * 1000) while timestamp last_timestamp: timestamp int(time.time() * 1000) return timestamp 完整代码示例
接下来就来整合一下上面的分解步骤这里将展示一个完整的Python语言代码示例后面会展示运行的最终结果。示例代码将按照上面的步骤来实现雪花算法并输出生成的唯一ID下面就是完整的示例代码
import time
import random class Snowflake: def __init__(self, worker_id, data_center_id): ### 机器标识IDself.worker_id worker_id ### 数据中心IDself.data_center_id data_center_id ### 计数序列号self.sequence 0 ### 时间戳self.last_timestamp -1 def next_id(self): timestamp int(time.time() * 1000) if timestamp self.last_timestamp: raise Exception(Clock moved backwards. Refusing to generate id for %d milliseconds % abs(timestamp - self.last_timestamp)) if timestamp self.last_timestamp: self.sequence (self.sequence 1) 4095 if self.sequence 0: timestamp self.wait_for_next_millis(self.last_timestamp) else: self.sequence 0 self.last_timestamp timestamp return ((timestamp - 1288834974657) 22) | (self.data_center_id 17) | (self.worker_id 12) | self.sequence def wait_for_next_millis(self, last_timestamp): timestamp int(time.time() * 1000) while timestamp last_timestamp: timestamp int(time.time() * 1000) return timestamp ### test
if __name__ __main__: worker_id 1 data_center_id 1 snowflake Snowflake(worker_id, data_center_id) for i in range(10): try: print(snowflake.next_id()) except Exception as e: print(Clock moved backwards:, e)运行结果演示
通过上面完整示例代码运行之后可以得到下面的运行结果即输出生成的唯一ID。具体的运行结果如下所示
[Running] python -u /Users/Aion/WorkSpace/PythonSpace/Snowflow/Snowflow.py
1742096523036069888
1742096523036069889
1742096523036069890
1742096523036069891
1742096523036069892
1742096523036069893
1742096523036069894
1742096523036069895
1742096523036069896
1742096523036069897[Done] exited with code0 in 0.057 seconds问题分析
(1)第一位为什么不使用
在计算机的表示中第一位是符号位0表示整数第一位如果是1则表示负数我们用的ID默认就是正数所以默认就是0那么这一位默认就没有意义。
(2)机器位怎么用
机器位或者机房位一共10 bit如果全部表示机器那么可以表示1024台机器如果拆分5 bit 表示机房5bit表示机房里面的机器那么可以有32个机房每个机房可以用32台机器。
(3)时间戳比较
在获取时间戳小于上一次获取的时间戳的时候不能生成ID而是继续循环直到生成可用的ID这里没有使用拓展位防止时钟回拨。
结束语
其实对于分布式ID的生成策略。无论是我们上述提到的哪一种。无非需要具有以下两种特点分布式、唯一。通过本文可以快速了解雪花ID雪花算法SnowFlakeSnowFlake的优点是 1单机上整体自增集群上整体自增整体上按照时间自增排序并且整个分布式系统内不会产生ID碰撞 2效率较高经测试SnowFlake每秒能够产生26万ID左右。 3强依赖性依赖与系统时间的一致性如果系统时间被回调或者改变可能会造成id冲突或者重复。 希望本文能帮助您理解雪花算法的实现过程也希望能够为您在分布式系统开发中提供一些使用帮助。 欢迎关注博主 「六月暴雪飞梨花」 或加入【六月暴雪飞梨花社区】一起学习和分享Linux、C、C、Python、Matlab机器人运动控制、多机器人协作智能优化算法滤波估计、多传感器信息融合机器学习人工智能等相关领域的知识和技术。