分布式id

是什么

分布式id是分布式系统中地一个全局唯一id。

为什么

以前业务量小的时候,进行系统开发一个mysql实例就可以提供服务,再大点的时候进行读写分离也可以应付过来,此时数据库主键自增就可以满足。但随着业务的不断扩展,读写分离扛不住后就需要进行分库分表,但在进行分库分表后就需要一个唯一的ID来标识一条记录

分布式id的条件

  • 全局唯一性:基本要求就是保证id的全局唯一性
  • 高性能:高性能低延时,ID生成响应快
  • 趋势递增:在MySQL InnoDB引擎中使用的是聚集索引,由于多数RDBMS使用B-tree的数据结构来存储索引数据,在主键的选择上面我们应该尽量使用有序的主键保证写入性能。
  • 信息安全:如果ID是连续的,恶意用户的扒取工作就非常容易做了,直接按照顺序下载指定URL即可;如果是订单号就更危险了,竞对可以直接知道我们一天的单量。所以在一些应用场景下,会需要ID无规则、不规则。

UUID

UUID(通用唯一编码),它是全球唯一的编码 可以使用,但不推荐

@Test
public void testUUID(){
    //利用hutool生成uuid
    String uuid = IdUtil.randomUUID();
    System.out.println(uuid);
}

UUID的生成非常简单,输出结果为 aad66041-58e2-4fc3-a728-29295086e343(可以去掉中间的 -),但是UUID并不适用于实际的业务开发中。

  • 优点

生成简单,本地生成没有网络消耗,具有唯一性

  • 缺点

无序的字符串,不具备趋势递增的特性
没有具体的业务含义
不仅长度过长,而且还是字符串,会导致mysql插入删除是数据位置变动频繁,而且字符串作为索引查询慢。

基于数据库自增ID

单数据库模式下使用数据库自增充当分布式ID是一个很好的选择。但是在高并发场景下,就不推荐使用了。

  • 优点

实现简单,ID自增,数值类型查询速度快

  • 缺点

DB单点存在宕机风险,无法抗住高并发场景

基于数据库集群模式

单点数据库方式扛不住高并发,存在宕机风险,那么就做成多主库模式集群,也就是多个mysql实例都能单独长生自增ID。那么这又会出现一个问题,多个mysql都是从1开始自增,会造成重复的ID。解决方案,设置起始值和自增步长。
假设是两个主库
主库1:

set @@auto_increment_offset = 1;     -- 起始值
set @@auto_increment_increment = 2;  -- 步长

主库2:

set @@auto_increment_offset = 2;     -- 起始值
set @@auto_increment_increment = 2;  -- 步长

这样两个库的主键自增分别为:

1 3 5 7 9
2 4 6 8 10

这种方法看似解决了自增和id唯一性的问题,但是随着业务量的增加,两个主库扛不住压力了,就需要进行mysql实例的扩展,此时就麻烦了,如果需要增加第三台主库,那么就需要从新设置三个主库的起始值和步长。

  • 优点:

解决了DB单点问题

  • 缺点:

不利于后续扩容

基于redis模式

Redis是单线程的并且reids中的incr命令是原子自增的。
redis是第三方的组件,如果本身系统中就没有使用redis,这时使用redis就会增加系统的负担,因为一旦使用就是集群,而且至少得三个哨兵集群。
redis如果使用RBD作为持久化,那在一个快照时间内宕机了,此时还未进行吃就会,恢复后会出现ID重复
使用AOF进行持久化,恢复较慢。(至少丢失1s得数据)

雪花算法

雪花算法时twitter开源得分布式id生成方案。其核心思想就是:使用一个64bit得long型数字作为全局唯一id

第一部分1个bit:0,二进制的最高位为符号位。0表示整数,1表示负数。
第二部分是41bit的时间戳。单位是毫秒。41bit可以表示的数字多达241-1,也就是可以标识241-1毫秒,约等于69年(从1970年开始)。
第三部分5个bit:表示机房id,最多表示2^5个机房
第四部分为5个bit:表示的是机器id。每个房间里可以有2^5个机器。
第五部分12个bit:表示序号,就是某个机房某台机器上一毫秒内同时生成的id的序号。12bit可以代表的最大正整数是2^12-1,一共4096个数,也就是说一毫秒内可以生成4096个唯一id。

  • 优点:
    高性能高可用,生成时不依赖于数据库,完全在内存中生成。
    容量大:每秒能生成百万的自增id
    id自增:时间时自增的,所以生成的id也是自增的。

  • 缺点:
    依赖与系统时间的一致性,如果系统时间被回调,或者改变,可能造成重复的id。

原文地址:https://www.cnblogs.com/liuzhidao/p/14848569.html