6位顺序号生成_高并发下分布式ID生成方案

在我们的开发过程中,只要你是涉及到高并发的领域,那么”怎么为你的系统生成一个高效、可靠、友好的ID”就是你的一个永远绕不开的问题。

本文档部分内容非原创,借鉴了网上的一些资源。涉及出处将在本文的最后部分列出。

一.分布式ID原则

  • 唯一性
  • 高效性
  • 可用性
  • 有序性

此处主要介绍为什么ID生成需要有序性

  • 写性能
在MySQL InnoDB引擎中使用的是聚集索引, 由于多数RDBMS使用B-tree的数据结构来存储索引数据,在主键的选择上面我们应该尽量使用有序的主键保证写入性能。 聚簇索引的数据的物理存放顺序与索引顺序是一致的,即:只要索引是相邻的,那么对应的数据一定也是相邻地存放在磁盘上的。 如果主键不是自增id,那么可以想象,它会干些什么,不断地调整数据的物理地址、分页,当然也有其他一些措施来减少这些操作, 但却无法彻底避免。但,如果是自增的,那就简单了,它只需要一页一页地写,索引结构相对紧凑,磁盘碎片少,效率也高。
  • 读性能
来感受下以下两个sql的性能吧,即使created_at字段也有索引: 1.select from table order by created_at2.select from table order by id ps: 根据磁盘预读的特性,如果第一次读取“1”,那么如果你是顺序存储,那么“2,3,4,5”也会被读取进内存中。 (当然一般ID就是你的聚簇索引,已经帮你排好序了)

二.实现方案

1. 数据库方案(auto_increment、Ticket Servers)

  • auto_increment

优点:

1.简单,代码方便,性能可以接受。 2.数字ID天然排序,对分页或者需要排序的结果很有帮助。

缺点:

1.可读性,容易暴露出库信息(今天下个订单,第二天同时间下个订单,其实就可以推测出该系统一天的订单量)。 2.在性能达不到要求的情况下,比较难于扩展。 3.如果遇见多个系统需要合并或者涉及到数据迁移会相当痛苦。 4.在单个数据库或读写分离或一主多从的情况下ÿ
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
雪花算法是种生成分布式ID的算法,它可以生成一个64ID,其中包含了时间戳、数据中心ID和机器ID等信息。下面是雪花算法生成分布式ID的软件设计模型: 1. 定义一个Snowflake类,该类包含以下属性: - datacenter_id: 数据中心ID,占5,取值围为0~31。 - worker_id: 机器ID,占5,取值范围为0~31。 - sequence: 序列号,占12,取值范围为0~4095。 - last_timestamp: 上一次生成ID的时间戳。 2. 实现Snowflake类的构造函数,初始化datacenter_id和worker_id属性。 3. 实现一个next_id方法,该方法用于生成下一个ID。具体实现如下: - 获取当前时间戳,单为毫秒。 - 如果当前时间戳小于上一次生成ID的时间戳,则说明系统时钟回退过,抛出异常。 - 如果当前时间戳等于上一次生成ID的时间戳,则将序列号加1。 - 如果当前时间戳大于上一次生成ID的时间戳,则将序列号重置为0,并将last_timestamp属性更新为当前时间戳。 - 将datacenter_id、worker_id、时间戳和序列号按照一定的数组合成一个64ID。 - 返回生成ID。 4. 在分布式系统中,每个节点都需要创建一个Snowflake实例,并指定不同的datacenter_id和worker_id。每个节点生成ID都是唯一的,且具有时间顺序。 下面是一个Python实现的雪花算法生成分布式ID的代码示例: ```python import time class Snowflake: def __init__(self, datacenter_id, worker_id): self.datacenter_id = datacenter_id self.worker_id = worker_id self.sequence = 0 self.last_timestamp = -1 def next_id(self): timestamp = int(time.time() * 1000) if timestamp < self.last_timestamp: raise Exception("Clock moved backwards. Refusing to generate id") if timestamp == self.last_timestamp: self.sequence = (self.sequence + 1) & 4095 if self.sequence == 0: timestamp = self.wait_next_millis(self.last_timestamp) else: self.sequence = 0 self.last_timestamp = timestamp return ((timestamp - 1288834974657) << 22) | (self.datacenter_id << 17) | (self.worker_id << 12) | self.sequence def wait_next_millis(self, last_timestamp): timestamp = int(time.time() * 1000) while timestamp <= last_timestamp: timestamp = int(time.time() * 1000) return timestamp ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值