基于雪花算法生成64位ID

基于雪花算法生成64位ID

import logging
import time


class Generator(object):
    """
    64位ID 1(符号位不用) (41(毫秒)+4(机器ID)+6(业务编码)+12(重复累加))

    基础时间(毫秒): 1577808000000 2020/01/01/ 00:00
    最大支持时间差: 2199023255551(0x1ffffffffffbit) 基于毫秒算大约可用69年(2199023255551/1000/60/60/24/365.25)
    dc: 4bit (自动取值范围[0,16))
    worker: 6bit (自动取值范围[0,64))
    desc: 同一时刻产生4095个id,原理上支持每秒409.5万个id,由于执行效率问题,本程序经测试每秒约能产生70万个id
    """
    EPOCH_TIMESTAMP = 1577808000000
    MAX_SEQUENCE = 4095  # 12bit 最大值

    def __init__(self, dc, worker):
        self.dc = dc
        self.worker = worker
        self.node_id = ((dc & 0xf) << 6) | (worker & 0x3f)  # 10bit = 4bit + 6bit
        self.last_timestamp = self.EPOCH_TIMESTAMP
        self.sequence = 0
        self.sequence_overload = 0
        self.errors = 0
        self.generated_ids = 0

    def get_next_id(self):
        """ id生产
        """
        curr_time = int(time.time() * 1000)
        if curr_time < self.last_timestamp:
            # stop handling requests til we've caught back up
            self.errors += 1
            raise Exception('Clock went backwards! %d < %d' % (curr_time, self.last_timestamp))

        if curr_time > self.last_timestamp:
            self.sequence = 0
            self.last_timestamp = curr_time

        self.sequence += 1
        if self.sequence > self.MAX_SEQUENCE:
            # the sequence is overload, just wait to next sequence
            logging.warning('The sequence has been overload')
            self.sequence_overload += 1
            time.sleep(0.001)
            return self.get_next_id()

        diff_time = curr_time - self.EPOCH_TIMESTAMP
        generated_id = ((diff_time & 0x1ffffffffff) << 22) | (self.node_id << 12) | self.sequence

        self.generated_ids += 1
        return generated_id

    @property
    def stats(self):
        """ 状态查询
        """
        return {
            'dc': self.dc,
            'worker': self.worker,
            'timestamp': int(time.time() * 1000),  # current timestamp for this worker
            'last_timestamp': self.last_timestamp,  # the last timestamp that generated ID on
            'sequence': self.sequence,  # the sequence number for last timestamp
            'sequence_overload': self.sequence_overload,  # the number of times that the sequence is overflow
            'errors': self.errors,  # the number of times that clock went backward
        }

    def pressure_test(self):
        """ 压力测试
        """
        start_time = int(time.time() * 1000)
        end_time = 1000 + start_time
        id_num = 0
        while self.last_timestamp <= end_time:
            self.get_next_id()
            id_num += 1
        print(id_num)


if __name__ == '__main__':
    a = Generator(0, 0)
    a.pressure_test()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值