osharp集成Yitter.IdGenerator并实现分布式ID

简介: 本文介绍了在 osharp 框架中集成 Yitter.IdGenerator 实现分布式 ID 的方法。osharp 是一个基于 .NET Core 的快速开发框架,而 Yitter.IdGenerator 是一种高效的分布式 ID 生成器。通过实现 `IKeyGenerator<long>` 接口并创建 `YitterSnowKeyGenerator` 类,结合 `YitterIdGeneratorPack` 模块化配置,实现了分布式环境下唯一 ID 的生成。

osharp集成Yitter.IdGenerator并实现分布式ID

前言

osharp是什么?请看https://github.com/dotnetcore/osharp

安装Yitter.IdGenerator

nuget安装Yitter.IdGenerator包

实现IKeyGenerator

using System;
using Microsoft.Extensions.Options;
using OSharp.Entity.KeyGenerate;
using OSharp.Data.Snows;
using Yitter.IdGenerator;
using IdGeneratorOptions = Yitter.IdGenerator.IdGeneratorOptions;

namespace Liuliu.Demo.Web.Startups.Yitter
{
    public class YitterSnowKeyGenerator : IKeyGenerator<long>
    {

        public YitterSnowKeyGenerator()
        {
        }

        public long Create()
        {
            return YitIdHelper.NextId();
        }
    }
}
AI 代码解读

实现YitterIdGeneratorPack

using System.ComponentModel;
using OSharp.Hosting.Identity.Entities;
using OSharp.Hosting.MultiTenancy;
using Microsoft.Extensions.DependencyInjection.Extensions;
using OSharp.Authorization;
using OSharp.Authorization.Modules;
using OSharp.Caching;
using OSharp.Core.Packs;
using OSharp.Core.Systems;
using OSharp.Entity;
using OSharp.Identity;
using Yitter.IdGenerator;
using Liuliu.Demo.Web.Startups.Yitter;
using OSharp.Entity.KeyGenerate;
using System.Configuration;
using Microsoft.Extensions.Options;
using OSharp.Exceptions;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.DotNet.Scaffolding.Shared;

namespace Liuliu.Demo.Web.Startups
{
    [DependsOnPacks(typeof(OsharpCorePack))]
    public class YitterIdGeneratorPack : OsharpPack
    {
        private const string MainLockName = "sys_idGen:workerId:lock";
        private const string MainValueKey = "sys_idGen:workerId:value";

        public YitterIdGeneratorPack()
        {
        }

        public override PackLevel Level => PackLevel.Framework;

        public override IServiceCollection AddServices(IServiceCollection services)
        {
            IConfiguration configuration = services.GetConfiguration();
            services.Configure<IdGeneratorOptions>(configuration.GetSection("IdGeneratorOptions"));               

            services.Replace<IKeyGenerator<long>, YitterSnowKeyGenerator>(ServiceLifetime.Singleton);
            return services;
        }

        override public void UsePack(IServiceProvider provider)
        {
            var _options = provider.GetRequiredService<IOptions<IdGeneratorOptions>>().Value;
            var _logger = provider.GetRequiredService<ILogger<YitterIdGeneratorPack>>();
            var workerId = GetWorkerId(provider, _options);
            var options = new IdGeneratorOptions
            {
                Method = _options.Method,
                BaseTime = _options.BaseTime,
                WorkerId = workerId,
                WorkerIdBitLength = _options.WorkerIdBitLength,
                SeqBitLength = _options.SeqBitLength,
                MaxSeqNumber = _options.MaxSeqNumber,
                MinSeqNumber = _options.MinSeqNumber,
                TopOverCostCount = _options.TopOverCostCount
            };

            _logger.LogInformation($"Yitter.IdGenerator已配置,WorkerId: {workerId}");
            YitIdHelper.SetIdGenerator(options);
        }

        private ushort GetWorkerId(IServiceProvider provider,IdGeneratorOptions options)
        {
            var lockName = $"{MainLockName}";
            var valueKey = $"{MainValueKey}";

            var minWorkId = 0;
            var maxWorkId = (int)Math.Pow(2, (double)options.WorkerIdBitLength);

            var cache = provider.GetRequiredService<IDistributedCache>();
            var _logger = provider.GetRequiredService<ILogger<YitterIdGeneratorPack>>();

            long workId = -1;
            var tempWorkIds = Enumerable.Range(minWorkId, maxWorkId).Select(id => id.ToString()).ToList();
            try
            {
                string workIdKey = "";
                foreach (var item in tempWorkIds)
                {
                    var workIdStr = item;
                    workIdKey = $"{valueKey}:{workIdStr}";
                    var exist = cache.Get<bool>(workIdKey);
                    if (exist)
                    {
                        workIdKey = "";
                        continue;
                    }

                    _logger.LogInformation($"############ 当前应用雪花WorkId:【{workIdStr}】############");

                    workId = long.Parse(workIdStr);
                    if (workId < minWorkId || workId > maxWorkId)
                        continue;

                    // 设置雪花Id算法机器码
                    YitIdHelper.SetIdGenerator(new IdGeneratorOptions
                    {
                        WorkerId = (ushort)workId,
                        WorkerIdBitLength = options.WorkerIdBitLength,
                        SeqBitLength = options.SeqBitLength
                    });

                    var cacheOptions = new DistributedCacheEntryOptions
                    {
                        AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(60)
                    };
                    cache.Set(workIdKey, true, cacheOptions);

                    break;
                }

                if (string.IsNullOrWhiteSpace(workIdKey)) throw new OsharpException("未设置有效的机器码,启动失败");

                // 开一个任务设置当前workId过期时间
                Task.Run(() =>
                {
                    while (true)
                    {
                        var cacheOptions = new DistributedCacheEntryOptions
                        {
                            AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(60)
                        };
                        cache.Set(workIdKey, true, cacheOptions);

                        Thread.Sleep(10000);
                    }
                });
            }
            catch (Exception ex)
            {
                throw new OsharpException($"{ex.Message};{ex.StackTrace};{ex.StackTrace}");
            }
            finally
            {

            }
            if(workId < minWorkId || workId >= maxWorkId) throw new OsharpException("未设置有效的机器码,启动失败");
            return (ushort)workId;
        }
    }
}
AI 代码解读

appsettings.Development.json加配置信息

  "IdGeneratorOptions": {
   
    "Method": 1,
    "BaseTime": "2025-01-01T00:00:00Z",
    "WorkerId": 2,
    "WorkerIdBitLength": 6,
    "SeqBitLength": 6,
    "MaxSeqNumber": 0,
    "MinSeqNumber": 5,
    "TopOverCostCount": 2000
  }
AI 代码解读

Startup.cs加载YitterIdGeneratorPack

.AddPack<YitterIdGeneratorPack> ()
AI 代码解读
目录
打赏
0
0
0
0
44
分享
相关文章
Spring Cloud Alibaba 集成分布式定时任务调度功能
定时任务在企业应用中至关重要,常用于异步数据处理、自动化运维等场景。在单体应用中,利用Java的`java.util.Timer`或Spring的`@Scheduled`即可轻松实现。然而,进入微服务架构后,任务可能因多节点并发执行而重复。Spring Cloud Alibaba为此发布了Scheduling模块,提供轻量级、高可用的分布式定时任务解决方案,支持防重复执行、分片运行等功能,并可通过`spring-cloud-starter-alibaba-schedulerx`快速集成。用户可选择基于阿里云SchedulerX托管服务或采用本地开源方案(如ShedLock)
206 1
[go 面试] 雪花算法与分布式ID生成
[go 面试] 雪花算法与分布式ID生成
分布式唯一ID生成:深入理解Snowflake算法在Go中的实现
在分布式系统中,确保每个节点生成的 ID 唯一且高效至关重要。Snowflake 算法由 Twitter 开发,通过 64 位 long 型数字生成全局唯一 ID,包括 1 位标识位、41 位时间戳、10 位机器 ID 和 12 位序列号。该算法具备全局唯一性、递增性、高可用性和高性能,适用于高并发场景,如电商促销时的大量订单生成。本文介绍了使用 Go 语言的 `bwmarrin/snowflake` 和 `sony/sonyflake` 库实现 Snowflake 算法的方法。
153 1
分布式唯一ID生成:深入理解Snowflake算法在Go中的实现
基于Redis海量数据场景分布式ID架构实践
【11月更文挑战第30天】在现代分布式系统中,生成全局唯一的ID是一个常见且重要的需求。在微服务架构中,各个服务可能需要生成唯一标识符,如用户ID、订单ID等。传统的自增ID已经无法满足在集群环境下保持唯一性的要求,而分布式ID解决方案能够确保即使在多个实例间也能生成全局唯一的标识符。本文将深入探讨如何利用Redis实现分布式ID生成,并通过Java语言展示多个示例,同时分析每个实践方案的优缺点。
131 8
分布式 ID 详解 ( 5大分布式 ID 生成方案 )
本文详解分布式全局唯一ID及其5种实现方案,关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
分布式 ID 详解 ( 5大分布式 ID 生成方案 )
Spring Cloud Alibaba 集成分布式定时任务调度功能
Spring Cloud Alibaba 发布了 Scheduling 任务调度模块 [#3732]提供了一套开源、轻量级、高可用的定时任务解决方案,帮助您快速开发微服务体系下的分布式定时任务。
15312 34
Redis 与 Scrapy:无缝集成的分布式爬虫技术
Redis 与 Scrapy:无缝集成的分布式爬虫技术
通用快照方案问题之通过Sleuth进行耗时分析和链路优化如何解决
通用快照方案问题之通过Sleuth进行耗时分析和链路优化如何解决
67 0
通用快照方案问题之通过Spring Cloud实现配置的自动更新如何解决
通用快照方案问题之通过Spring Cloud实现配置的自动更新如何解决
104 0
分布式自增ID算法---雪花算法(SnowFlake)Java实现
分布式自增ID算法---雪花算法(SnowFlake)Java实现
377 0

热门文章

最新文章