mybatisplus雪花算法id重复日记
雪花算法组成:
由于mysql数据库长整型最大64位,最大值为2的63次方-1。所以雪花算法最大也只能是64位。
第一位符号位0表示正数
后41位表示时间戳,最大值也就是2的41次方毫秒,除去一年1000*60*60*24*365毫秒,约等于69年。
再5位的数据中心id,5位的机器id,最大值31,加上为0的情况,有32*32种可能。
最后12位序列号,最大值4095,加上0,4096种可能。也就是一毫秒能产生4096个雪花序列。
其他变种
百度的UidGenerator雪花算法,缩短时间戳位数,也就是减少了使用时间。大约8.7年用完,就是超出28位了。
MyBatisPlus自带的雪花算法实现DefaultIdentifierGenerator
核心的数据中心id:根据当前服务机器的MAC地址,转16进制低位对32取模。
机器id:数据中心id+jvm进程id,转16进制低位对32取模。
id重复问题:由于微服务环境是容器,获取到宿主机mac地址是一样的,导致数据中心id重复,并且jvm的 pid,取模后也可能重复,造成不同机器,雪花算法的数据中心id和机器id是相同的,产生的id也就可能相同。
解决办法:手动指定数据中心id和机器id
手动指定方案:
1、数据中心id:每个服务appid固定分配不同的[0-31]值。
2、机器id:考虑容器环境下,服务会重启、扩容、宕机等场景,机器id需要每次分配都是新的,不重复的需求。
我们每个应用服务的集群,大约有8~9台机器。
基于以上前提,制定使用数据库保证分布式唯一机器id,每台机器启动时主动到数据库插入一行记录,获取到自增的id,对32取模,得出机器id。
这样每台机器都能有序的获取到机器id。
实现springRunner,在容器启动后,注入SqlSessionFactory执行以上逻辑即可。手动指定完雪花算法实现类参数会新生成实现类,需要替换SqlSessionFactory里面的MybatisConfiguration的GlobalCofig里的IdentifierGenerator实现类。
机器id重复场景思考:只要一个应用的集群机器数量不超过16台,并且不存在超过16台机器重启,其余不重启的情况,就不会有重复机器id的问题。
比如有20台机器,开始分配0-19机器id,突然5-19的机器都重启了,那势必会有机器与0-4的重复。
这个情况基本忽略。