区块链技术博客
www.b2bchain.cn

葵花宝典—分布式ID

这篇文章主要介绍了葵花宝典—分布式ID的讲解,通过具体代码实例进行17537 讲解,并且分析了葵花宝典—分布式ID的详细步骤与相关技巧,需要的朋友可以参考下https://www.b2bchain.cn/?p=17537

本文实例讲述了2、树莓派设置连接WiFi,开启VNC等等的讲解。分享给大家供大家参考文章查询地址https://www.b2bchain.cn/7039.html。具体如下:

目录

      • 方案一:UUID:通用唯一标识码:
      • 方案二:数据库主键自增:
      • 方案三:Redis:
      • 方案四:雪花算法:
        • 4.1:了解64比特:
        • 4.2:时钟回拨问题:
        • 4.3:雪花算法的移位操作:
        • 4.4:雪花算法的python版本:

方案一:UUID:通用唯一标识码:

  • 1: UUID包括:网卡MAC地址、时间戳、名字空间(Namespace)、随机或伪随机数、时序等元素。
  • 2:UUID是由128位二进制组成,一般转换成十六进制,然后用String表示。
  • 3: UUID的优点::3.1:通过本地生成,没有经过网络I/O,性能较快。3.2:无序,无法预测他的生成顺序。
  • 4: UUID的缺点:4.1:128位二进制一般转换成36位的16进制,太长了只能用String存储,空间占用较多。 4.2:不能生成递增有序的数字。

方案二:数据库主键自增:

  • 1:大家对于唯一标识最容易想到的就是主键自增,这个也是我们最常用的方法。例如我们有个订单服务,那么把订单id设置为主键自增即可。
  • 2:单独一个数据库存储,id主键自增就可以了。
  • 3:如果数据在不同的数据库存储,假设有3台,则设置初始值分别是 1 2 3 步长分别为3进行递增。
  • 4:优点:简单方便,有序递增,方便排序和分页。
  • 5:缺点:
  • 5.1:分库分表会带来问题,需要进行改造。
  • 5.2:并发性能不高,受限于数据库的性能。
  • 5.3:简单递增容易被其他人猜测利用,比如你有一个用户服务用的递增,那么其他人可以根据分析- 5.4:注册的用户ID来得到当天你的服务有多少人注册,从而就能猜测出你这个服务当前的一个大概状况。
  • 5.5:数据库宕机服务不可用。

方案三:Redis:

  • 1:Redis中有两个命令Incr,IncrBy,因为Redis是单线程的所以能保证原子性。
  • 2:优点:性能比数据库好,能满足有序递增。
  • 3:缺点1:由于redis是内存的KV数据库,即使有AOF和RDB,但是依然会存在数据丢失,有可能会造成ID重复。
  • 4:缺点2:依赖于redis,redis要是不稳定,会影响ID生成。

方案四:雪花算法:

4.1:了解64比特:

  • 1bit:符号位
  • 41bit:时间戳:这里可以记录69年。
  • 10bit:10bit用来记录机器ID,总共可以记录1024台机器,一般用前5位代表数据中心,后面5位是某个数据中心的机器ID
  • 12bit:循环位,用来对同一个毫秒之内产生不同的ID,12位可以最多记录4095个,也就是在同一个机器同一毫秒最多记录4095个,多余的需要进行等待下毫秒。
    葵花宝典---分布式ID

4.2:时钟回拨问题:

因为机器的原因会发生时间回拨,我们的雪花算法是强依赖我们的时间的,如果时间发生回拨,有可能会生成重复的ID,在我们上面的nextId中我们用当前时间和上一次的时间进行判断,如果当前时间小于上一次的时间那么肯定是发生了回拨,算法会直接抛出异常.

4.3:雪花算法的移位操作:

葵花宝典---分布式ID

4.4:雪花算法的python版本:

import time import logging  class InvalidSystemClock(Exception):     """     时钟回拨异常     """     pass  # 64位ID的划分 WORKER_ID_BITS = 5 DATACENTER_ID_BITS = 5 SEQUENCE_BITS = 12  # 最大取值计算 MAX_WORKER_ID = -1 ^ (-1 << WORKER_ID_BITS)  # 2**5-1 0b11111 MAX_DATACENTER_ID = -1 ^ (-1 << DATACENTER_ID_BITS)  # 移位偏移计算 WOKER_ID_SHIFT = SEQUENCE_BITS DATACENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATACENTER_ID_BITS  # 序号循环掩码 SEQUENCE_MASK = -1 ^ (-1 << SEQUENCE_BITS)  # Twitter元年时间戳 TWEPOCH = 1288834974657   logger = logging.getLogger('flask.app')   class IdWorker(object):     """     用于生成IDs     """      def __init__(self, datacenter_id, worker_id, sequence=0):         """         初始化         :param datacenter_id: 数据中心(机器区域)ID         :param worker_id: 机器ID         :param sequence: 其实序号         """         # sanity check         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:int timestamp         """         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 until {}'.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 << WOKER_ID_SHIFT) | self.sequence         return new_id      def _til_next_millis(self, last_timestamp):         """         等到下一毫秒         """         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()) 

本文转自互联网,侵权联系删除葵花宝典—分布式ID

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » 葵花宝典—分布式ID
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们