应用实践|基于Python手把手教你实现雪花算法

这篇具有很好参考价值的文章主要介绍了应用实践|基于Python手把手教你实现雪花算法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

python生成图片雪花算法,技术应用,# 技术|开发工具,python,算法,雪花算法,Snowflake

📫 作者简介:「六月暴雪飞梨花」,专注于研究Java,就职于科技型公司后端工程师
🏆 近期荣誉:华为云云享专家、阿里云专家博主、
🔥 三连支持:欢迎 ❤️关注、👍点赞、👉收藏三连,支持一下博主~

概述

分布式策略ID的主要应用在互联网网站、搜索引擎、社交媒体、在线购物、金融、大数据处理、日志场景中,这些应用需要支持大量的并发请求和用户访问,分布式ID策略可以通过请求分发到不同的服务器节点来做计算,以提高服务的响应速度和可用性。
常见的分布式ID生成策略:
● UUID(Universally Unique Identifier)
● 雪花算法(Snowflake)
● Redis原子自增
● 基于数据库的自增主键(有些数据库不支持自增主键)
● 取当前毫秒数
本文主要简单介绍下雪花ID算法(Snowflake)的Python语言的计算方法。
python生成图片雪花算法,技术应用,# 技术|开发工具,python,算法,雪花算法,Snowflake

雪花算法(Snowflake)是 Twitter 开源的分布式ID生成算法。雪花ID,或称雪花,是分布式计算中使用的唯一标识符的一种形式。该格式由Twitter创建,用于推文的ID。人们普遍认为,每片雪花都有唯一的结构,因此他们取了“雪花ID”这个名字。在当时Twitter的团队从MySQL转向Cassandra时,需要一种新的方法来生成ID号,而Cassandra中没有顺序ID生成工具,所以,应运而生雪花ID出现了。

雪花算法的相关知识可以参考Github:https://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的结构可以用图表示如下:
python生成图片雪花算法,技术应用,# 技术|开发工具,python,算法,雪花算法,Snowflake

代码演示步骤

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):  
        ### 机器标识ID
        self.worker_id = worker_id  
        ### 数据中心ID
        self.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):  
        ### 机器标识ID
        self.worker_id = worker_id  
        ### 数据中心ID
        self.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 code=0 in 0.057 seconds

问题分析

(1)第一位为什么不使用

在计算机的表示中,第一位是符号位,0表示整数,第一位如果是1则表示负数,我们用的ID默认就是正数,所以默认就是0,那么这一位默认就没有意义。

(2)机器位怎么用

机器位或者机房位,一共10 bit,如果全部表示机器,那么可以表示1024台机器,如果拆分,5 bit 表示机房,5bit表示机房里面的机器,那么可以有32个机房,每个机房可以用32台机器。

(3)时间戳比较

在获取时间戳小于上一次获取的时间戳的时候,不能生成ID,而是继续循环,直到生成可用的ID,这里没有使用拓展位防止时钟回拨。

结束语

其实对于分布式ID的生成策略。无论是我们上述提到的哪一种。无非需要具有以下两种特点:分布式、唯一。通过本文,可以快速了解雪花ID(雪花算法,SnowFlake),SnowFlake的优点是:
(1)单机上整体自增,集群上整体自增,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞;
(2)效率较高,经测试,SnowFlake每秒能够产生26万ID左右。
(3)强依赖性,依赖与系统时间的一致性,如果系统时间被回调,或者改变,可能会造成id冲突或者重复。
希望本文能帮助您理解雪花算法的实现过程,也希望能够为您在分布式系统开发中提供一些使用帮助。


欢迎关注博主 「六月暴雪飞梨花」 或加入【六月暴雪飞梨花社区】一起学习和分享Linux、C、C++、Python、Matlab,机器人运动控制、多机器人协作,智能优化算法,滤波估计、多传感器信息融合,机器学习,人工智能等相关领域的知识和技术。文章来源地址https://www.toymoban.com/news/detail-833293.html

到了这里,关于应用实践|基于Python手把手教你实现雪花算法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 用Python手把手教你实现一个爬虫(含前端界面)

    前言 爬虫基本原理 使用Python的requests库发送HTTP请求 使用BeautifulSoup库解析HTML页面 使用PyQt5构建前端界面 实现一个完整的爬虫程序 结语 随着互联网的飞速发展,再加上科技圈的技术翻天覆地的革新,互联网上每天都会产生海量的数据,这些数据对于企业和个人都具有重要的

    2024年04月28日
    浏览(49)
  • 【Python操作IPYNB文件】——手把手教你实现自动化

    【Python操作IPYNB文件】——手把手教你实现自动化 对于经常使用Jupyter Notebook的人来说,手动进行一些重复性工作是很繁琐的,比如将多个ipynb文件合并为一个,或者将一个大的ipynb文件拆分成多个小文件。这时候,我们就需要用到Python来自动化处理这些问题。 1. 安装依赖库

    2024年02月05日
    浏览(56)
  • 【实践篇】手把手教你落地DDD

    常见的DDD实现架构有很多种,如经典四层架构、六边形(适配器端口)架构、整洁架构(Clean Architecture)、CQRS架构等。架构无优劣高下之分,只要熟练掌握就都是合适的架构。本文不会逐个去讲解这些架构,感兴趣的读者可以自行去了解。 本文将带领大家从日常的三层架构

    2024年02月06日
    浏览(80)
  • 手把手教你实现—基于OpenCV的车流量统计和车速检测代码

             本章将实现了一个简单的车辆速度估计和车流量统计的GUI应用,它使用了Haar级联检测器和相关跟踪器来检测和跟踪视频中的车辆,并通过图像处理和数学计算来估计车辆的速度。         1.首先,该代码需要cv2:用于图像处理和计算机视觉任务;dlib:用于对象

    2024年02月04日
    浏览(55)
  • 手把手教你基于【SpringBoot+MyBatis】实现员工管理系统‍【附完整源码】

    Hello,你好呀,我是 灰小猿 ,一个超会写 BUG 的程序猿🙊! 近期在学习springboot框架相关的内容,相比于SSM, SpringBoot最大的特点就是集成了Spring和SpringMVC,让之前繁琐的配置工作变得更加简洁, 同时对于业务逻辑层的处理也更加的友好, 所以今天就使用 SpringBoot整合MyBati

    2023年04月08日
    浏览(45)
  • AIGC|手把手教你进行ChatGLM模型部署实践

    模型部署基本步骤分为模型选择、模型部署、运行,如果需要在特定的场景下定制化模型,则还需要进行数据集的选择、数据集格式转换、微调。 根据上述的步骤本教程选取如下的开源模型、数据集,来对医疗场景下进行定制化模型部署。当然模型部署对GPU要求非常高,所以

    2024年02月03日
    浏览(49)
  • 手把手教你使用Python实现推箱子小游戏(附完整源码)

    我们这个项目是一个基于Python实现的推箱子小游戏,名叫Sokoban: 这个游戏的目的是让玩家,也就是大写的 P ,推着箱子 # ,填充用小写的 o 标记的地面上的洞 该版本的Sokoban的规则如下: 游戏在矩形的二维网格上举行,其 原点(0,0) 位于左上方 网格上的每个单元格可以随时包

    2024年02月03日
    浏览(53)
  • 动手实践丨手把手教你用STM32做一个智能鱼缸

    摘要: 本文基于STM32单片机设计了一款基于物联网的智能鱼缸。 本文分享自华为云社区《基于STM32+华为云IOT设计的物联网鱼缸【玩转华为云】》,作者: DS小龙哥 。 为了缓解学习、生活、工作带来的压力,提升生活品质,许多人喜欢在家中、办公室等场所养鱼。为节省鱼友

    2024年01月16日
    浏览(49)
  • 线上FullGC问题排查实践——手把手教你排查线上问题

    作者:京东科技 韩国凯 问题起因是我们收到了jdos的容器CPU告警,CPU使用率已经达到104% 观察该机器日志发现,此时有很多线程在执行跑批任务。正常来说,跑批任务是低CPU高内存型,所以此时考虑是FullGC引起的大量CPU占用(之前有类似情况,告知用户后重启应用后解决问题

    2024年02月02日
    浏览(49)
  • YOLOv5入门实践(4)——手把手教你训练自己的数据集

      在上一篇文章中我们介绍了如何划分数据集,划分好之后我们的前期准备工作就已经全部完成了,下面开始训练自己的数据集吧! 前期回顾: YOLOv5入门实践(1)——手把手带你环境配置搭建 YOLOv5入门实践(2)——手把手教你利用labelimg标注数据集

    2024年04月10日
    浏览(67)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包