网易公开课分享:
分布式、高并发下ID生成要求
1.全局唯一
2.趋势递增
3.效率高(生成、使用、索引)
4.控制并发
策略一:UUID/GUID (通用唯一识别码)
UUID按照开放软件基金会(OSF)制定的标准计算。
用到了以太网地址(MAC)、纳秒级时间、芯片ID码和随机数。
由以下几个部分的组合:
- 当前日期和时间,UUID的第一个部分与时间有关,如果你在生成一个UUID之后,过几秒又生成一个UUID,则第一个部分不同,其余相同。
- 时钟序列
- 全局唯一的IEEE机器识别号(如果有网卡,从网卡获得,没有网卡以其他方式获得)
示例UUID
a15d2c9f-84c0-48f9-a8e7-70c47bcf2ddd
策略一的优缺点
优点: 1.使用简单 2.不依赖其他组件 3.不影响数据库拓展
缺点:1.数据库索引效率低-数据库在新建索引的时候,都会按照索引字段的顺序排序的,如果生成的索引字段刚好有序的,那么在构建索引的时候效率高,否则每次都要进行重排序操作。
2.uuid产生的字符串太长,且无实际业务意义,可读性差。
3.长度36的字符串,占据空间大
4.应用集群环境,机器多是,出现重复几率大。
策略二:数据库自增长字段
我们知道,mysql数据库使用auto_increment.自增长字段,在集群环境下,不同的库设置不同的初始值,如每次自增加100
Mysql下修改起点和步长的方式
set @@auto_increment_offset=1; --设置起点
set @@auto_increment_increment=100; 设置步长为100;
show variables like ‘auto_inc%’;-- 查看参数
数据库1:设置初始值1 步长100 自增字段 1 101 201 301 401 .........1201
数据库2:设置初始值2 步长 100 自增字段 2 102 202 302 402 ........ 1202
数据库3:设置初始值3 步长 100 自增字段 3 103 203 303 403 ...........1203
等等...
策略2的优缺点:
优点:1.无需编码 2. 性能过得去 3.索引友好
缺点:1.大表不能做水评分表,否则插入删除一出现问题。比如数据库1. 数据库的数据过多,将其拆分,拆分后的表与新表的插入删除策略定制容易出现问题
2.以来前期规划,拓展麻烦. 如初始值100位,如数据量过于的大,100张表已经不够第101张表初始值没法设置
3.以来mysql内部维护“自增锁”,高并发下插入数据影响性能。
4.在业务中操作父、子表(关联表)插入时,要“先父后子”。比如user,order要先insert user表获取id,才能新增order表存储关联的外键。
策略三:推特的雪花算法
策略四:基于redis自增
思路:利用增长技术API,业务系统在自增长的基础上,配合其他信息组长成为一个唯一的id。
Redis的incr(key)用于将key进行自增,并返回增长的数值。
redis有如下特性:单线程原子操作、自增计数API、数据有效期机制EX
示例 1.业务编码+地区+自增数值(9 020 00000000000001)
优点:
1.扩展性强,可以方便的结合业务进行处理
2.利用redis操作原子性的特性,保证在并发的时候不会重复。
缺点:
1.引入redis就意味着引入第三方依赖,要单独维护redis集群,保证redis服务的高可用
2.增加一次网略开销。
策略 | 优点 | 缺点 |
uuid | 实现简单,不占用带宽 | 无序、占空间、可读性差、索引不友好 |
数据库自增 | 无代码调整、递增 | DB单点故障、扩展性瓶颈 |
雪花算法 | 性能优、不占贷款、趋势递增 | 依赖服务器时间 |
基于redis自研 | 无单点故障、性能优于DB、递增、扩展灵活 | 占用宽带、Redis集群维护 |