Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >应用实践|基于Python手把手教你实现雪花算法

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

作者头像
艾特
发布于 2024-01-25 00:35:46
发布于 2024-01-25 00:35:46
58400
代码可运行
举报
运行总次数:0
代码可运行

概述

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

雪花算法(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的结构可以用二进制格式表示如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
0 1                                       41     51         64
+-----------------------------------------+------+-----------+
|0|timestamp (milliseconds since epoch)   |worker| sequence  |
+-----------------------------------------+------+-----------+

Snowflake ID的结构可以用图表示如下:

代码演示步骤

1 引入依赖库

使用Python标准库中的time模块来获取当前时间戳,并使用random模块来生成随机worker_id和data_center_id。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import time  
import random  

2 初始化参数

此处我们定义一个类Snowflake类,提前初始化机器标识ID、数据中心ID、计数序列号、时间戳。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    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返回。 具体代码如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    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,并打印出来。如果时钟回退,则会抛出一个异常并打印错误信息。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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超过序列号的最大值时,需要等待下一毫秒再生成。具体代码如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    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,下面就是完整的示例代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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。具体的运行结果如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[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冲突或者重复。 希望本文能帮助您理解雪花算法的实现过程,也希望能够为您在分布式系统开发中提供一些使用帮助

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-01-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
基于Go语言手把手教你实现雪花算法
根据推特官方的介绍,雪花算法是由Twitter开发的一种全局唯一ID生成算法,它的设计目标是在分布式系统中生成唯一ID,具备趋势递增、高性能、可扩展等特点。其实雪花算法生成的唯一ID是由64位二进制数组成,可以分解为三个部分:
三掌柜
2023/12/26
1.1K2
基于Go语言手把手教你实现雪花算法
雪花算法:分布式系统唯一ID生成算法
雪花算法(Snowflake Algorithm)是一种用于生成分布式系统中唯一ID的算法。起初由Twitter设计,用于解决分布式系统中唯一ID的需求。这一算法的目标是生成全局唯一、有序的64位整数ID,以确保数据不冲突、不重复。
Jensen_97
2023/09/19
4.1K0
雪花算法:分布式系统唯一ID生成算法
Go语言实现Snowflake雪花算法
每次放长假的在家里的时候,总想找点简单的例子来看看实现原理,这次我们来看看 Go 语言雪花算法。
luozhiyun
2021/05/03
5.5K0
雪花算法snowflake
本文主要介绍SnowFlake 算法,是 Twitter 开源的分布式 id 生成算法。
在下是首席架构师
2022/08/02
1.3K0
使用雪花算法生成流水号!
" 在分布式系统中常见的问题就是如何生成流水号,一般情况下会有专门的流水号系统,不过在开发过程中或者开发早期不一定会有专门流水号系统,在这里介绍下我所使用的流水号生成器——雪花算法"
程序员小航
2020/11/23
1.6K0
使用雪花算法生成流水号!
雪花算法的使用(java)
雪花算法(Snowflake)是一种分布式唯一 ID 生成算法,能够生成唯一的、有序的、高可用的 ID,常用于分布式系统中作为全局唯一标识符(GUID)。雪花算法生成的 ID 是一个 64 位的整数,其中高位是时间戳,中间位是机器 ID,低位是序列号。
魚迹
2023/05/06
1.1K0
雪花算法:分布式唯一ID生成利器
无论是在分布式系统中的ID生成,还是在业务系统中请求流水号这一类唯一编号的生成,都是软件开发人员经常会面临的一场景。而雪花算法便是这些场景的一个解决方案。
程序新视界
2022/05/06
1.2K0
雪花算法:分布式唯一ID生成利器
探讨面试常见问题雪花算法、时钟回拨问题,java中优雅的实现方式
在大数据量系统中,分布式ID生成是一个关键问题。为了保证在分布式环境下生成的ID唯一、有序且高效,业界提出了多种解决方案,其中雪花算法(Snowflake Algorithm)是一种广泛应用的分布式ID生成算法。本文将详细介绍雪花算法的原理、实现及其处理时钟回拨问题的方法,并提供Java代码示例。
小马哥学JAVA
2024/10/13
4230
Java系列之雪花算法和原理
SnowFlake 算法:是 Twitter 开源的分布式 id 生成算法。 核心思想:使用一个 64 bit 的 long 型的数字作为全局唯一 id。 首先了解一下雪花ID的结构:从网上盗用一张;
沁溪源
2020/11/24
1.2K0
Java系列之雪花算法和原理
分布式ID中的SnowFlake
雪花算法这一在分布式架构中很常见的玩意,但一般也不需要怎么去深入了解,一方面一般个人项目用不到分布式之类的大型架构,另一方面,就算要用到,市面上很多ID生成器也帮我们完成了这项工作。不过出于学习,本文也简单来介绍一下它的实现和原理。
阿新的杂记
2023/08/28
3770
分布式ID中的SnowFlake
分布式ID生成系统之雪花算法详解
在当今的云计算和微服务架构盛行的时代,分布式系统已成为软件开发的重要组成部分。随着系统规模的扩大和业务的复杂化,对数据一致性和唯一性的要求也越来越高,尤其是在全局唯一标识符(ID)的生成上。因此,分布式ID生成系统应运而生,成为保证数据唯一性和提高系统可扩展性的关键技术之一。雪花算法(Snowflake)是Twitter开源的一种算法,用于生成64位的全局唯一ID,非常适用于分布式系统中生成唯一标识符。下面我们将深入探讨雪花算法的原理、结构和实现方式。
修己xj
2024/03/04
6000
分布式ID生成系统之雪花算法详解
雪花算法的原理,掌握后去勇闯天涯!
SnowFlake 算法,是 Twitter 开源的分布式 id 生成算法。其核心思想就是:使用一个 64 bit 的 long 型的数字作为全局唯一 id。在分布式系统中的应用十分广泛,且ID 引入了时间戳,基本上保持自增的,后面的代码中有详细的注解。
二哥聊运营工具
2021/12/17
3050
雪花算法的原理,掌握后去勇闯天涯!
啥?asong要出新系列之雪花算法(go)
雪花算法产生的背景当然是twitter高并发环境下对唯一ID生成的需求,得益于twitter内部牛逼的技术,雪花算法能够流传于至今并且被广泛使用,是因为它有几个特点
Golang梦工厂
2022/07/07
3480
啥?asong要出新系列之雪花算法(go)
浩鲸科技:为什么要用雪花ID替代数据库自增ID?
今天咱们来看一道数据库中比较经典的面试问题:为什么要使用雪花 ID 替代数据库自增 ID?同时这道题也出现在了浩鲸科技的 Java 面试中,下面我们一起来看吧。
磊哥
2023/11/30
5000
浩鲸科技:为什么要用雪花ID替代数据库自增ID?
【黄啊码】百万级别订单量,如何生成唯一订单ID(雪花算法)
Twitter-SnowFlake算法的产生是源于Twitter为了满足自己业务(每秒上万条消息的请求,每条消息都必须分配一条唯一的id,并且在分布式系统中不同机器产生的id必须不同)的需求。
黄啊码
2022/06/15
6420
分布式唯一 ID 之 Snowflake 算法
Snowflake(雪花) 是一项服务,用于为 Twitter 内的对象(推文,直接消息,用户,集合,列表等)生成唯一的 ID。这些 IDs 是唯一的 64 位无符号整数,它们基于时间,而不是顺序的。完整的 ID 由时间戳,工作机器编号和序列号组成。当在 API 中使用 JSON 数据格式时,请务必始终使用 id_str 字段而不是 id,这一点很重要。这是由于处理JSON 的 Javascript 和其他语言计算大整数的方式造成的。如果你遇到 id 和 id_str 似乎不匹配的情况,这是因为你的环境已经解析了 id 整数,并在处理的过程中仔细分析了这个数字。
阿宝哥
2019/11/06
1.8K0
分布式唯一 ID 之 Snowflake 算法
框架篇:分布式全局唯一ID
每一次HTTP请求,数据库的事务的执行,我们追踪代码执行的过程中,需要一个唯一值和这些业务操作相关联,对于单机的系统,可以用数据库的自增ID或者时间戳加一个在本机递增值,即可实现唯一值。但在分布式,又该如何实现唯一性的ID
潜行前行
2021/07/23
6950
java雪花算法实现
Java的雪花算法(Snowflake)是一种生成全局唯一ID的算法,它基于时间戳和节点ID生成一个64位的ID。
堕落飞鸟
2023/03/29
5850
Twitter雪花算法PHP实现库Snowflake
在分布式系统中,生成全局唯一的ID是一项常见的需求。Snowflake是Twitter开源的一种分布式ID生成算法,它可以在分布式环境下生成唯一的、趋势递增的ID,且不依赖于中央服务器。本文将介绍Snowflake算法的原理,使用PHP实现Snowflake生成器。
Tinywan
2024/08/14
2400
Twitter雪花算法PHP实现库Snowflake
一文读懂“Snowflake(雪花)”算法
Snowflake 中文的意思为雪花,所以 Snowflake算法 常被称为 雪花算法,是 Twitter(现“X”)开源的分布式 ID 生成算法,是一种分布式主键ID生成的解决方案。
Blue_007
2023/11/27
14.1K1
一文读懂“Snowflake(雪花)”算法
相关推荐
基于Go语言手把手教你实现雪花算法
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验