详细分析Python模块中的雪花算法(附模板)

news2024/11/23 23:46:03

目录

  • 前言
  • 1. 基本知识
  • 2. 模板
  • 3. Demo

前言

分布式ID的生成推荐阅读:分布式ID生成方法的超详细分析(全)

1. 基本知识

Snowflake 算法是一种用于生成全局唯一 ID 的分布式算法,最初由 Twitter 设计并开源

它被设计用于解决分布式系统中生成唯一 ID 的需求,特别是在微服务架构和大规模分布式系统中

Snowflake 算法的核心思想是利用时间戳、工作机器 ID 和序列号来生成全局唯一的 64 位长整型 ID

其核心的组成部分如下:

  • 时间戳(Timestamp):通常以毫秒为单位,用于标识生成 ID 的时间点。时间戳的精度对 ID 的唯一性至关重要

  • 工作机器 ID(Worker ID):用于标识不同的工作机器或节点。在分布式系统中,每个节点需要有唯一的标识

  • 数据中心 ID(Datacenter ID):用于标识不同的数据中心。在大规模分布式系统中,可能存在多个数据中心,每个数据中心需要有唯一的标识

  • 序列号(Sequence Number):用于解决同一时间戳下生成多个 ID 的冲突问题。序列号通常是一个自增的数字,通过与一定的位数掩码进行位运算来确保不会溢出

Snowflake 算法的作用:

  • 生成全局唯一 ID:Snowflake 算法可以在分布式系统中生成全局唯一的 ID,确保不同节点生成的 ID 不会冲突

  • 适用于分布式环境:由于Snowflake算法只依赖于机器的时钟和网络通信,因此非常适合在分布式环境中使用

  • 简单且高效:Snowflake 算法的实现相对简单,且性能高效,可以快速生成唯一 ID

2. 模板

以下模板带有注释

实现了一个 Snowflake 类,通过调用 generate 方法可以生成唯一的 Snowflake ID

Snowflake ID 是一个 64 位长整型,包含了时间戳、数据中心 ID、工作机器 ID 和序列号等信息

import time

class SnowFlake(object):
    def __init__(self, worker_id, datacenter_id, sequence=0):
        self.worker_id = worker_id  # 用于标识不同的工作机器
        self.datacenter_id = datacenter_id  # 用于标识不同的数据中心
        self.sequence = sequence  # 序列号,用于解决并发生成的 ID 冲突
        self.tw_epoch = 1288834974657  # Twitter Snowflake epoch (in milliseconds),Snowflake 算法的起始时间点
        
        # Bit lengths,用于计算位数
        self.worker_id_bits = 5  # 5位,最大值为31
        self.datacenter_id_bits = 5  # 5位,最大值为31
        self.max_worker_id = -1 ^ (-1 << self.worker_id_bits)  # 最大工作机器 ID
        self.max_datacenter_id = -1 ^ (-1 << self.datacenter_id_bits)  # 最大数据中心 ID
        self.sequence_bits = 12  # 12位,支持的最大序列号数
        self.sequence_mask = -1 ^ (-1 << self.sequence_bits)  # 序列号掩码,用于生成序列号
        
        # Create initial timestamp,初始化上一次生成 ID 的时间戳
        self.last_timestamp = self.current_timestamp()
        
        # Check worker_id and datacenter_id values,检查工作机器 ID 和数据中心 ID 的取值范围
        if self.worker_id > self.max_worker_id or self.worker_id < 0:
            raise ValueError(f"Worker ID must be between 0 and {self.max_worker_id}")
        if self.datacenter_id > self.max_datacenter_id or self.datacenter_id < 0:
            raise ValueError(f"Datacenter ID must be between 0 and {self.max_datacenter_id}")
    
    @staticmethod
    def current_timestamp():
        return int(time.time() * 1000)  # 获取当前时间戳,单位为毫秒
    
    def generate(self):
        timestamp = self.current_timestamp()  # 获取当前时间戳
        
        if timestamp < self.last_timestamp:  # 如果当前时间戳小于上一次生成 ID 的时间戳
            raise ValueError("Clock moved backwards. Refusing to generate ID for {} milliseconds".format(
                self.last_timestamp - timestamp))  # 抛出异常,时钟回拨
        
        if timestamp == self.last_timestamp:  # 如果当前时间戳等于上一次生成 ID 的时间戳
            self.sequence = (self.sequence + 1) & self.sequence_mask  # 增加序列号,并与序列号掩码进行与运算,防止溢出
            if self.sequence == 0:  # 如果序列号归零
                timestamp = self.wait_next_millis(self.last_timestamp)  # 等待下一毫秒
        else:
            self.sequence = 0  # 时间戳变化,序列号重置为零
        
        self.last_timestamp = timestamp  # 更新上一次生成 ID 的时间戳
        
        # Generate Snowflake ID,生成 Snowflake ID
        _id = ((timestamp - self.tw_epoch) << (self.worker_id_bits + self.datacenter_id_bits)) | (
                self.datacenter_id << self.worker_id_bits) | self.worker_id << self.sequence_bits | self.sequence  # 使用时间戳、数据中心 ID、工作机器 ID 和序列号生成 ID
        return f"{_id:016d}"  # 返回 64 位长整型 ID 的字符串表示,补齐到16位长度
    
    def wait_next_millis(self, last_timestamp):
        timestamp = self.current_timestamp()  # 获取当前时间戳
        while timestamp <= last_timestamp:  # 循环直到获取到下一毫秒的时间戳
            timestamp = self.current_timestamp()
        return timestamp  # 返回下一毫秒的时间戳

3. Demo

结合以上模板,放一个调用的过程:

# 示例用法
if __name__ == "__main__":
    # 假设有两个数据中心,每个数据中心有两个工作机器
    worker_id = 1
    datacenter_id = 1
    
    snowflake = SnowFlake(worker_id, datacenter_id)
    
    # 生成10个ID
    for i in range(10):
        print(snowflake.generate())

截图如下:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1531871.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

设计模式|工厂模式

文章目录 1. 工厂模式的三种实现2. 简单工厂模式和工厂方法模式示例3. 抽象工厂模式示例4. 工厂模式与多态的关系5. 工程模式与策略模式的关系6. 面试中可能遇到的问题6.1 **工厂模式的概念是什么&#xff1f;**6.2 **工厂模式解决了什么问题&#xff1f;**6.3 **工厂模式的优点…

C++ 模板入门详解

目录 0. 模板引入 1.函数模板 1. 函数重载的缺点 2. 函数模板的概念和格式 2. 函数模板的实例化 2.1 隐式实例化&#xff1a;让编译器根据实参推演模板参数的实际类型 2.2 显式实例化&#xff1a;在函数名后的<>中指定模板参数的实际类型 2.3 函数模板参数的匹…

蓝桥杯刷题-替换字符

代码&#xff1a; 顺着题目意思写即可 sinput() nint(input()) for i in range(n):l, r, x, y input().split() if x not in s[int(l)-1:int(r)]: # 如果待替换字符不在区间内则跳过continueelse:# 找到待替换字符的位置&#xff0c;用replace函数进行替换ss[:int(l)-1]s[in…

Linux-docker安装数据库mysql

1、拉去mysql镜像&#xff1a; docker pull mysql2、创建容器挂载路径 mkdir -p /usr/local/jiuxiang/mysql/data # 数据存储位置 mkdir -p /usr/local/jiuxiang/mysql/logs # 日志存储位置 mkdir -p /usr/local/jiuxiang/mysql/conf # 配置文件3、启动容器 docker run -…

STL第一弹

2 STL初识 2.1 STL的诞生 长久以来&#xff0c;软件界一直希望建立一种可重复利用的东西 C的面向对象和泛型编程思想&#xff0c;目的就是复用性的提升 大多情况下&#xff0c;数据结构和算法都未能有一套标准,导致被迫从事大量重复工作为了建立数据结构和算法的一套标准,诞生…

MySQL的基本操作与增删改查管理操作

一、MySQL数据库sql语句 1.1 sql 命令 database数据库table表row行column列user用户select从数据表中获取数据updata更新数据库中的数据delete从数据库中删除数据insert into 向数据表插入数据create database创建新数据库alter database修改数据库create table创建新表alter…

蓝桥杯 2023 省B 飞机降落

首先&#xff0c;这题要求的数据量比较少&#xff0c;我们可以考虑考虑暴力解法。 这题可能难在很多情况的考虑&#xff0c;比如说&#xff1a; 现在时间是10&#xff0c;有个飞机20才到&#xff0c;我们是可以干等10分钟。 #include <iostream> #include <…

【机器学习300问】39、高斯分布模型如何实现异常检测?

一、异常检测是什么&#xff1f; &#xff08;1&#xff09;举几个例子 ① 信用卡交易异常检测 在信用卡交易数据分析中&#xff0c;如果某个用户的消费习惯通常是小额且本地化消费&#xff0c;那么突然出现一笔大额且跨国的交易就可能被标记为异常。 ② 电机温度异常检测 在电…

echart trigger 为 axis 的时候不显示 tooltip 解决办法

echart trigger 为 axis 的时候不显示 tooltip 解决办法 在项目 vitetsvue3 中使用 echart 显示了一个曲线图&#xff1a; 但当把图表的 trigger 设置成 axis 的时候&#xff0c;鼠标扫过并不显示具体的数值&#xff0c;如上图所示。 但 trigger item 的时候是正常的。 解决…

Docker Desktop 安装 ClickHouse 超级简单教程

Docker desktop 安装 clickhouse 超级简单 文章目录 Docker desktop 安装 clickhouse 超级简单 什么是 Docker &#xff1f;安装下准备安装Docker配置安装 ClickHouse配置数据库密码DBeaver 测试创建表总结 什么是 Docker &#xff1f; 下载 Docker desktop Docker Desktop …

[蓝桥杯 2015 省 B] 生命之树

水一水的入门树形DP #include<iostream> #include<algorithm> #include<vector> using namespace std; using ll long long; #define int long long const int N 2e610; const int inf 0x3f3f3f3f; const int mod 1e97;int n; int w[N]; vector<vecto…

Node.js快速入门:搭建基础Web服务器与实现CRUD及登录功能

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

Word2vec 学习笔记

word2vec 学习笔记 0. 引言1. Word2vec 简介1-1. CBOW1-2. SG 2. 实战 0. 引言 最近研究向量检索&#xff0c;看到有同事使用 MeCab、Doc2Vec&#xff0c;所以把 Word2vec 这块知识学习一下。 1. Word2vec 简介 Word2vec 即 word to vector&#xff0c;顾名思义&#xff0c;…

在MongoDB建模1对N关系的基本方法

“我在 SQL 和规范化数据库方面拥有丰富的经验&#xff0c;但我只是 MongoDB 的初学者。如何建立一对 N 关系模型&#xff1f;” 这是我从参加 MongoDB 分享日活动的用户那里得到的最常见问题之一。 我对这个问题没有简短的答案&#xff0c;因为方法不只有一种&#xff0c;还有…

HarmonyOS(鸿蒙)ArkUI组件

方舟开发框架&#xff08;简称ArkUI&#xff09;为HarmonyOS应用的UI开发提供了完整的基础设施&#xff0c;包括简洁的UI语法、丰富的UI功能&#xff08;组件、布局、动画以及交互事件&#xff09;&#xff0c;以及实时界面预览工具等&#xff0c;可以支持开发者进行可视化界面…

风速预测(八)VMD-CNN-Transformer预测模型

往期精彩内容&#xff1a; 时序预测&#xff1a;LSTM、ARIMA、Holt-Winters、SARIMA模型的分析与比较-CSDN博客 风速预测&#xff08;一&#xff09;数据集介绍和预处理-CSDN博客 风速预测&#xff08;二&#xff09;基于Pytorch的EMD-LSTM模型-CSDN博客 风速预测&#xff…

负数,小数转换二进制

负数转换二进制 例&#xff1a;在带符号整数signed char的情况下&#xff0c;-57如何被表示成负数呢&#xff1f;在计算机中又是如何计算66-57呢&#xff1f; 解析 考虑int占有32位太长&#xff0c;因此使用只占8位的signed char类型来举例。57用二进制表示位00111001&#…

【Mysql数据库基础04】连接查询、内连接、外连接

Mysql数据库基础04 0 该博客所要用的数据库表的属性1 SQL92 内连接1.1 等值连接1.1.1 两个表的顺序可以调换1.1.2 加筛选1.1.3 加分组1.1.4 加排序1.1.5 三表连接 1.2 非等值连接1.3 自连接 2 SQL99 内连接2.1 等值连接2.2 非等值连接2.3 自连接 3 外连接3.1 左外和右外连接 4 …

大模型主流微调训练方法总结 LoRA、Adapter、Prefix-tuning、P-tuning、Prompt-tuning 并训练自己的数据集

大模型主流微调训练方法总结 LoRA、Adapter、Prefix-tuning、P-tuning、Prompt-tuning 概述 大模型微调(finetuning)以适应特定任务是一个复杂且计算密集型的过程。本文训练测试主要是基于主流的的微调方法:LoRA、Adapter、Prefix-tuning、P-tuning和Prompt-tuning,并对…

网络原理(3)——TCP协议

目录 一、连接管理 二、三次握手 1、何为三次握手&#xff1f; 2、三次握手有何意义&#xff1f; 三、四次挥手 三次握手和四次挥手的相似之处和不同之处 &#xff08;1&#xff09;相似之处 &#xff08;2&#xff09;不同之处 四、TCP的状态 建立连接&#xff1a; 断开…