SnowFlake算法

SnowFlake算法

问题:如何在分布式集群中生成全局唯一的ID?

方法一:UUID

UUID是通用唯一识别码 (Universally Unique Identifier),在其他语言中也叫GUID,可以生成一个长度32位的全局唯一识别码。

//e493a18e-61d0-499a-87c1-650d03735edb
String uuid = UUID.randomUUID().toString()

UUID可以保证全局唯一,但是占用32位有些太长,而且是无序的,入库时性能较差。

众所周知,关系型数据库的索引大都是B+树的结构,拿ID字段来举例,索引树的每一个节点都存储着若干个ID。
如果我们的ID按递增的顺序来插入,比如陆续插入8,9,10,新的ID都只会插入到最后一个节点当中。当最后一个节点满了,会裂变出新的节点。这样的插入是性能比较高的插入,因为这样节点的分裂次数最少,而且充分利用了每一个节点的空间。
但是,如果我们的插入完全无序,不但会导致一些中间节点产生分裂,也会白白创造出很多不饱和的节点,这样大大降低了数据库插入的性能。

方法二:数据库自增主键

为了提高性能,在分布式系统中可以用DB proxy请求不同的分库,每个分库设置不同的初始值,步长和分库数量相等:这样一来,DB1生成的ID是1,4,7,10,13….,DB2生成的ID是2,5,8,11,14…..

ID的生成对数据库严重依赖,不仅影响性能,而且数据库一旦挂掉,服务不可用。

方法三:SnowFlake算法

SnowFlake所生成的ID一共分成四部分:

  • 第一位:占用1bit,其值始终是0,没有实际作用。
  • 时间戳:占用41bit,精确到毫秒,总共可以容纳约140年的时间。
  • 工作机器ID:占用10bit,其中高位5bit是数据中心ID(datacenterId),低位5bit是工作节点ID(workerId),做多可以容纳1024个节点。
  • 序列号:占用12bit,这个值在同一毫秒同一节点上从0开始不断累加,最多可以累加到4095。

同一毫秒可以生成1024*4096个ID。

SnowFlake算法的优缺点

SnowFlake算法的优点:
1.生成ID时不依赖于DB,完全在内存生成,高性能高可用。
2.ID呈趋势递增,后续插入索引树的时候性能较好。
SnowFlake算法的缺点:
依赖于系统时钟的一致性。如果某台机器的系统时钟回拨,有可能造成ID冲突,或者ID乱序。

你可能感兴趣的:(算法)