高并发下分布式ID生成方案
在我们的开发过程中,只要你是涉及到高并发的领域,那么”怎么为你的系统生成一个高效、可靠、友好的ID”就是你的一个永远绕不开的问题。 本文档部分内容非原创,借鉴了网上的一些资源。涉及出处将在本文的最后部分列出。 一.分布式ID原则 唯一性 高效性 可用性 有序性 此处主要介绍为什么ID生成需要有序性 写性能 在MySQL InnoDB引擎中使用的是聚集索引, 由于多数RDBMS使用B-tree的数据结构来存储索引数据,在主键的选择上面我们应该尽量使用有序的主键保证写入性能。 聚簇索引的数据的物理存放顺序与索引顺序是一致的,即:只要索引是相邻的,那么对应的数据一定也是相邻地存放在磁盘上的。 如果主键不是自增id,那么可以想象,它会干些什么,不断地调整数据的物理地址、分页,当然也有其他一些措施来减少这些操作, 但却无法彻底避免。但,如果是自增的,那就简单了,它只需要一页一页地写,索引结构相对紧凑,磁盘碎片少,效率也高。 读性能 来感受下以下两个sql的性能吧,即使created_at字段也有索引: 1.select from table order by created_at 2.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.在单个数据库或读写分离或一主多从的情况下,只有一个主库可以生成。有单点故障的风险。 优化方案 针对主库单点,如果有多个Master库,则每个Master库设置的起始数字不一样,步长一样, 可以是Master的个数。 ...