为什么要了解snowFlake算法?
在分布式系统中,当数据量大到一定程度后,就不得不面临分库分表的问题,分库分表后每条数据需要有一个全局唯一的id。
当然可以使用UUID(通用唯一识别码),生成一个长度32位的全局唯一识别码。
但是这种uuid长度有32位,而且是无序的,会对极大的影响数据库性能。
关系型数据库的索引大都是B+树的结构,有序的数据会通常会在一个叶子节点中,之后节点满了才会分裂出新的节点。但是如果数据无序的话,就会导致不断分裂出新的节点,浪费了存储空间的同时,也极大的影响查入性能。
snowFlake
如图,SnowFlake生成的ID一共分成四部分:
1.占位
占用1bit,值始终是0,没有实际作用。
2.时间戳
占用41bit,精确到毫秒,总共可以容纳约140年的时间。
3.机器id
占用10bit,其中高位5bit是数据中心ID(datacenterId),低位5bit是工作节点ID(workerId),做多可以容纳1024个节点。
4.序列号
占用12bit,同一毫秒同一机器上从0递增,最大4095。
SnowFlake的优点
1)因为有机器id,所以不用考虑集群生成重复ID。
2)高性能高可用。
时钟回拨问题
依赖于时间戳保证的一致性,如果某台机器的系统时钟回拨,生成的ID可能和之前的ID冲突。
解决方法:
1)针对并发量较少的场景,一毫秒可能用不了4095。可以占用一部分序列号,记录上一次生成id的时间,发现出现回拨,在原本的基础上加上固定的值,然后再递增序列号。
2)AtomicLong递增的方式取代时间戳,自己计算时间,但是这会导致id中的时间并非真正的时间。
shardingsphere
shardingsphere支持snowflake算法生成id,有兴趣的话可以看下我之前写的文章