【Web_数据库自动化_雪花算法_分布式批量生成不重复的唯一ID】Snowflake&&pysnowflake,通过python实现雪花算法,生成唯一ID值,常用于数据准备阶段。

参考文章: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。

四、雪花算法的优点在于:

  1. 高效:雪花算法使用简单,计算速度快,可以轻松地嵌入到各种语言和框架中,支持高并发场景下的ID生成。

  2. 全局唯一:雪花算法生成的ID是全局唯一的,不需要复杂的协调机制,可以方便地应用于分布式系统中。

  3. 趋势递增:雪花算法生成的ID按照时间戳递增排序,方便对数据进行排序和查询。

  4. 可配置性:雪花算法支持根据需求自定义位数,可以支持多种应用场景。

五、但是雪花算法也有一些缺点:

  1. 依赖于系统时钟:雪花算法的ID生成依赖于系统时钟,如果系统时钟回拨或者发生调整,可能会导致生成的ID不唯一或趋势逆序。

  2. 可读性差:由于雪花算法生成的ID是64位的数字,对人类来说比较难以理解和记忆。

总体来说,雪花算法是一种简单、高效、可扩展的分布式唯一ID生成算法,在分布式系统中广泛应用。但是需要注意的是,在使用时要注意系统时钟同步以及生成的ID长度适当。

六、通过python实现雪花算法

#!/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())

七、通过python第三方库生成雪花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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值