在 Furion 框架中,可以使用 Snowflake 算法来生成全局唯一的自增单号。Snowflake 算法是 Twitter 开源的分布式 ID 生成算法,通过组合时间戳、机器 ID 和序列号来保证生成的 ID 在分布式环境中不重复。

下面是在 Furion 框架中实现获取自增单号的方法的示例代码:

using System;
using Furion.DependencyInjection;

namespace YourNamespace
{
    public interface IIdGenerator
    {
        long GenerateId();
    }

    [SkipScan] // 在 Furion 框架中注册为单例服务,跳过扫描
    public class SnowflakeIdGenerator : IIdGenerator
    {
        private readonly object _lock = new object();
        private long _lastTimestamp = -1;
        private long _sequence = 0;
        private const long Twepoch = 1288834974657L; // 起始时间戳,可以根据实际情况调整
        private const int WorkerIdBits = 5; // 机器 ID 所占的位数
        private const int DatacenterIdBits = 5; // 数据中心 ID 所占的位数
        private const int SequenceBits = 12; // 序列号所占的位数

        private readonly long _maxWorkerId = -1L ^ (-1L << WorkerIdBits); // 机器 ID 的最大值
        private readonly long _maxDatacenterId = -1L ^ (-1L << DatacenterIdBits); // 数据中心 ID 的最大值
        private readonly long _workerId; // 机器 ID
        private readonly long _datacenterId; // 数据中心 ID

        public SnowflakeIdGenerator()
        {
            _workerId = GetWorkerId();
            _datacenterId = GetDatacenterId();
        }

        public long GenerateId()
        {
            lock (_lock)
            {
                var timestamp = GetCurrentTimestamp();

                if (timestamp < _lastTimestamp)
                {
                    throw new Exception('Clock moved backwards. Refusing to generate id.');
                }

                if (timestamp == _lastTimestamp)
                {
                    _sequence = (_sequence + 1) & SequenceMask;
                    if (_sequence == 0)
                    {
                        timestamp = TilNextMillis(_lastTimestamp);
                    }
                }
                else
                {
                    _sequence = 0;
                }

                _lastTimestamp = timestamp;

                var id = ((timestamp - Twepoch) << TimestampLeftShift)
                         | (_datacenterId << DatacenterIdShift)
                         | (_workerId << WorkerIdShift)
                         | _sequence;

                return id;
            }
        }

        private long TilNextMillis(long lastTimestamp)
        {
            var timestamp = GetCurrentTimestamp();
            while (timestamp <= lastTimestamp)
            {
                timestamp = GetCurrentTimestamp();
            }
            return timestamp;
        }

        private long GetCurrentTimestamp()
        {
            return DateTimeOffset.UtcNow.Ticks / TimeSpan.TicksPerMillisecond;
        }

        private long GetWorkerId()
        {
            // 在实际应用中,可以根据机器的特定标识来获取 workerId
            // 这里只是简单示范,使用一个随机数模拟
            var random = new Random();
            var workerId = random.Next((int)_maxWorkerId);
            return workerId;
        }

        private long GetDatacenterId()
        {
            // 在实际应用中,可以根据数据中心的特定标识来获取 datacenterId
            // 这里只是简单示范,使用一个随机数模拟
            var random = new Random();
            var datacenterId = random.Next((int)_maxDatacenterId);
            return datacenterId;
        }

        private const long TimestampLeftShift = SequenceBits + WorkerIdBits + DatacenterIdBits;
        private const long DatacenterIdShift = SequenceBits + WorkerIdBits;
        private const long WorkerIdShift = SequenceBits;
        private const long SequenceMask = -1L ^ (-1L << SequenceBits);
    }
}

上述代码中,SnowflakeIdGenerator 类实现了 IIdGenerator 接口,在每次调用 GenerateId 方法时,根据当前时间戳、机器 ID 和序列号生成一个全局唯一的自增单号。为了确保生成的 ID 在分布式环境中不重复,需要根据实际情况设置合适的机器 ID 和数据中心 ID。

在高并发场景下,为了保证线程安全,使用 lock 关键字对关键代码块进行加锁。同时,在生成 ID 时,如果当前时间戳小于上次生成 ID 的时间戳,则抛出异常,避免出现重复单号。

注意:上述代码中的机器 ID 和数据中心 ID 的获取方式只是简单示范,实际应用中需要根据具体的环境和需求来确定。

Furion 框架实现高并发自增单号生成 (不使用数据库自增主键)

原文地址: https://www.cveoy.top/t/topic/qet9 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录