.NET集成Yitter.IdGenerator实现分布式Id,并使用redis自动注册WorkerId

参考文章
多语言新雪花算法(SnowFlake IdGenerator)

添加依赖

Install-Package Yitter.IdGenerator -Version 1.0.14

自动注册WorkerId的动态库下载

这是一个go语言版本的dll,内部使用了redis实现了自动注册WorkerId。使用这个库需要先安装好redis。

https://github.com/yitter/IdGenerator/releases/download/v1.3.1/regworkerid_lib_v1.3.1.zip

下载好后,我把它解压到了Host项目下的lib\regworkerid_lib_v1.3.1\yitidgengo.dll路径

创建YitIdInitHelper类

    public class YitIdInitHelper
    {
        //定义dll路径
        public const string RegWorkerId_DLL_NAME = "lib\\regworkerid_lib_v1.3.1\\yitidgengo.dll";
        //根据文档定义三个接口
        [DllImport(RegWorkerId_DLL_NAME, EntryPoint = "RegisterOne", CallingConvention = CallingConvention.Cdecl, ExactSpelling = false)]
        // 注册一个 WorkerId,会先注销所有本机已注册的记录
        // ip: redis 服务器地址
        // port: redis 端口
        // password: redis 访问密码,可为空字符串“”
        // maxWorkerId: 最大 WorkerId
        private static extern ushort RegisterOne(string ip, int port, string password, int maxWorkerId);

        [DllImport(RegWorkerId_DLL_NAME, EntryPoint = "UnRegister", CallingConvention = CallingConvention.Cdecl, ExactSpelling = false)]
        // 注销本机已注册的 WorkerId
        private static extern void UnRegister();

        [DllImport(RegWorkerId_DLL_NAME, EntryPoint = "Validate", CallingConvention = CallingConvention.Cdecl, ExactSpelling = false)]
        // 检查本地WorkerId是否有效(0-有效,其它-无效)
        private static extern int Validate(int workerId);

        public static long NextId()
        {
            //这个if判断在高并发的情况下可能会有问题
            if (YitIdHelper.IdGenInstance == null)
            {
                UnRegister();
                
                // 如果不用自动注册WorkerId的话,直接传一个数值就可以了
                var workerId = RegisterOne("127.0.0.1", 6379, "", 63);
                // 创建 IdGeneratorOptions 对象,可在构造函数中输入 WorkerId:
                var options = new IdGeneratorOptions(workerId);
                // options.WorkerIdBitLength = 10; // 默认值6,限定 WorkerId 最大值为2^6-1,即默认最多支持64个节点。
                // options.SeqBitLength = 6; // 默认值6,限制每毫秒生成的ID个数。若生成速度超过5万个/秒,建议加大 SeqBitLength 到 10。
                // options.BaseTime = Your_Base_Time; // 如果要兼容老系统的雪花算法,此处应设置为老系统的BaseTime。
                // ...... 其它参数参考 IdGeneratorOptions 定义。

                // 保存参数(务必调用,否则参数设置不生效):
                YitIdHelper.SetIdGenerator(options);

                // 以上过程只需全局一次,且应在生成ID之前完成。
            }

            return YitIdHelper.NextId();
        }
    }

为实体类Id加上一个特性

//可以显式为Id赋值的特性
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public override long Id { get; set; }

改完实体类之后,修改一下表结构,可能需要删掉原来的Id列。

测试

我重写了dbcontext类的SaveChangesAsync方法,所以不需要显式调用YitIdInitHelper.NextId(),如果没有重写的话,显式调用YitIdInitHelper.NextId(),为Id赋值就行了。
        [HttpPost]
        public async Task Add()
        {
            var msg = "测试数据2";
            var currentTime = DateTime.Now;

            await _dbContext.Set<ToDoItem>().AddAsync(new ToDoItem()
            {
                //Id = YitIdInitHelper.NextId(),
                CreationTime = currentTime,
                Text = msg
            });

            await _dbContext.SaveChangesAsync();

        }

可以看到已经成功生成分布式Id了,我这里生成的是15位,Js Number最大16位,根据文档的说法可以用好几十年。

posted @ 2022-11-30 19:58  cnblogsName  阅读(2774)  评论(0编辑  收藏  举报