先看图中雪花算法的结构
第一段1位,固定0, 69年以后可能会用1,也就是说默认在一个系统中只能用最多69年,如果征用第一位可以使用139年。
第二段41位,用时间毫秒数数表示41位大概是69年多,默认表示1971年1月1日到当前时间的毫秒数,有的雪花算法优化支持设定这个起算时间,我们可以把它指定位我们系统立项的时间,这样的好处在于可以使用完整的69年,第一位改成1,还可以用在用70年,一句话,可以用到死。
第三段10位,2的10次方,同样1024 个标识符,可用最多支持1024 台节点的分布式器群。1024 多余中小公司来说太多了,有些多雪花算法的包装把它分成2段,workerId和datacenterId一段5位,也就是32个值。分别表示不同的服务和同一个服务的不同集群节点。
第四段12位,2的12次方4096个,这个是内部加锁单调递增的。也就是每毫秒最多产出4096个,如果你的业务需要单机平均每毫秒生产的数据量大于4096,那么大概不适合学号算法,或者你改改默认的算法,把第三段用不完的借几位给第4段。如果你的系统只是阶段性的超过没毫秒4096,雪花算法依旧是可以支持的,比如当前毫秒如果不够用了,就自动使用下一个毫秒应该生成的id。我们也可以指定这个向后面的毫秒应该生成的id借最多能接几个毫秒的(注意的是,hutool里面有个bugs)。一般默认不指定,每毫秒4096 以后就重复了,hutool 的默认做法死重复以后就等待到下一毫秒。
下面是一个hutool雪花算法的实现:默认使用时间是2010-11-4 9:42:54(DEFAULT_TWEPOCH),而不是1971年1月1日,默认是没毫秒生产id超过4096个以后就重复,但是可以通过设置timeOffset来指定最多向后面借多个毫秒的ID//
//测试例子(测试使用hutool 生产409600个ID ,100毫秒默认生成的最大值,后面 new Snowflake(new Date(), 0, 0, false, 409600000) 最后指的的 偏移毫秒数,我随便指定的,只要大于 100 就行)
hutool 的写法 用时:
修正后的耗时:
正确性验证代码:生成 409600 个 id并且去重复,然后得到生成的个数
结果:
hutool 版本 5.7.22
雪花算法,要保持全局唯一,必须要指定唯一的dataCenterId和 workerId,正常这两个数都是0-31 之间的一个值。
如果我们自己的商用节点,应该依赖注册中心计数器之类的自动设置dataCenterId和 workerId,如果是小集群,固定几台机子手动的为每隔节点指定 dataCenterId和workerId也行(比如读取指定目录下的一个文件)
hutool 里面的 雪花算法能用吗?
hutool里面的没有注册中心,所以不能保证全局唯一的dataCenterId和workId
但是 hutool里面里面的 dataCenterId 是通过物理地址算出来的,然后workId 是通过 dataCenterId+当前进程Id 算出来的.
结论:同一台物理机上 dataCenterId会相等,不同物理机的 dataCenterId 大概率不会相等
同一个Java进程里面 workId 会相等,Java进程重启 workId 会变化 大概率不会相等
所以可以简单的看成hutool随机的指定了dataCenterId和workId重复的概率 1/255 分之一,