一个分布式ID的生成器-雪花算法

18 篇文章 1 订阅
8 篇文章 0 订阅

#coding:utf-8
'''
create on 2020-11-23

@author:sandy
'''

import time
class SnowFlake(object):

    def __init__(self,datacenterId,machineId):
        
        self.sequence = 0
        self.laststmp = -1

        self.sequence_bit = 12
        self.machine_bit = 5
        self.datacenter_bit = 5

        self.max_datacenter_num = -1 ^ (-1 << self.datacenter_bit)
        self.max_machine_num = -1 ^ (-1 << self.machine_bit)
        self.max_sequence_num = -1 ^ (-1 << self.sequence_bit)

        self.machine_left = self.sequence_bit
        self.datacenter_left = self.sequence_bit + self.machine_bit
        self.timestmp_left = self.datacenter_left + self.datacenter_bit

        print(self.max_datacenter_num,self.max_machine_num,self.max_sequence_num)
        
        
        if datacenterId > self.max_datacenter_num or datacenterId < 0:
            raise Exception("datacenterId",datacenterId)

        if machineId > self.max_machine_num or machineId < 0:
            raise Exception("machineId",machineId)

        self.start_stmp = 1606118422000L
        self.datacenterId = datacenterId
        self.machineId = machineId

    def nextId(self):
        curstmp = self.getNewStmp()
        if curstmp < self.laststmp:
            raise Exception("Clock moved backwards.  Refusing to generate id")
        if curstmp == self.laststmp:
            self.sequence = (self.sequence + 1) & self.max_sequence_num
            if self.sequence == 0:
                time.sleep(0.001)
                curstmp = self.getNewStmp()
            else:
                pass
        else:
            self.sequence = 0

        self.laststmp = curstmp
        ret =  (curstmp - self.start_stmp) << self.timestmp_left | self.datacenterId << self.datacenter_left | self.machineId << self.machine_left | self.sequence
        return ret
    

    def getNewStmp(self):
        return int(time.time() * 1000)

if __name__ == '__main__':
    flake = SnowFlake(5,5)
    for i in range(1000):
        nextid = flake.nextId()
        print(nextid)

snowflake的结构如下(每部分用-分开):

 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000  第一位为未使用,

接下来的41位为毫秒级时间(41位的长度可以使用69年),

然后是5位datacenterId和5位workerId(10位的长度最多支持部署1024个节点)

最后12位是毫秒内的计数(12位的计数顺序号支持每个节点每毫秒产生4096个ID序号)

如果1ms内生成的数超过4096个  也就是self.sequence = (self.sequence + 1) & self.max_sequence_num 后 self.sequence == 0 这种情况,对于碰到这种情况 sleep 一下  当然也有其他的方式解决这种情况

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值