Blog .NET项目中有多种数据类生成对象实例时需要唯一标识,一般做法要么使用GUID,也可以保存到数据库时使用数据库表的自增长ID,也可以自定义规则以确保产生不重复的唯一标识,而在Blog .NET项目中使用雪花算法生成唯一标识。
关于雪花算法的原理介绍见参考文献4,Blog .NET项目使用的雪花算法代码源自参考文献3,雪花算法生成类为SnowflakeId,位于App.Framwork项目内,命名空间为App.Framwork.Generate。雪花算法类主要供App.Application项目和App.Hosting项目使用,其引用关系及具体文件如下图所示:
SnowflakeId类支持返回long类型的唯一标识(函数名NextId)和字符串型唯一标识(函数名为NextStringId),后者其实是调用NextId().ToString生成。
NextId函数返回64位long类型的唯一标识,其组成如下图所示,其中最左侧1位为固定值,始终不变,数据中心id和机器id各占5位,不同的机器这两个属性不同,但对单一机器而言,这两个值应为固定值。在NextId函数中主要处理时间戳和顺序号。
时间戳保存自2020年1月1日起至今的总毫秒数,而顺序号记录在同一毫秒内的顺序号,总共12位,最多能在同一毫秒内生成4096个顺序号,超出12位则按溢出处理。生成唯一标识的算法逻辑如下图所示,在此不再赘述。
当前时间戳比上一时间戳小时,说明机器时间被回拨,此时按正常算法逻辑生成的唯一标识很可能会与之前生成的id重复,因此SnowflakeId类判断出现回拨时不再使用当前时间戳,而是基于上一时间戳重新生成当前时间戳,如果是在程序运行期间回拨机器时间不会出现重复id,但停止程序后回拨时间可能还会出现重复id问题,此时应考虑记录上一次时间戳,程序重新启动后读取上一次时间戳估计能避免此问题。
参考文献:
[1]https://gitee.com/miss_you/Blog
[2]https://www.donet5.com/Home/Doc
[3]https://www.cnblogs.com/sunyuliang/p/12161416.html
[4]https://blog.csdn.net/xiaoye319/article/details/105988057/