C# 生成有序Guid的几种方法

public sealed class SequentialGuid
    {
        //使用 Guid.NewGuid() 的字节重排
        /// <summary>
        /// 优点及适用场景:
        /// 1.系统只在应用层生成GUID,追求极致的插入性能和最低的索引碎片
        /// 2.系统并发量极高,需要最高的时间戳精度来避免冲突(因为使用系统滴答计数(Tick),精度为100纳秒)
        /// </summary>
        /// <param name="guidType"></param>
        /// <returns></returns>
        public static Guid Create(SequentialGuidType guidType = SequentialGuidType.SequentialAsString)
        {
            var randomBytes = Guid.NewGuid().ToByteArray();

            var timeBytes = BitConverter.GetBytes(DateTime.UtcNow.Ticks);

            if (BitConverter.IsLittleEndian)
                Array.Reverse(timeBytes);

            byte[] sequentialBytes;

            switch (guidType)
            {
                case SequentialGuidType.SequentialAsString:
                case SequentialGuidType.SequentialAsBinary:
                    sequentialBytes = new byte[16];
                    Buffer.BlockCopy(timeBytes, 2, sequentialBytes, 0, 6);
                    Buffer.BlockCopy(randomBytes, 0, sequentialBytes, 6, 10);
                    break;

                case SequentialGuidType.SequentialAtEnd:
                    sequentialBytes = new byte[16];
                    Buffer.BlockCopy(randomBytes, 0, sequentialBytes, 0, 10);
                    Buffer.BlockCopy(timeBytes, 2, sequentialBytes, 10, 6);
                    break;

                default:
                    throw new ArgumentOutOfRangeException("guidType");
            }

            return new Guid(sequentialBytes);
        }

        public enum SequentialGuidType
        {
            SequentialAsString,
            SequentialAsBinary,
            SequentialAtEnd
        }
        

        //使用 Comb GUID 算法
        /// <summary>
        /// 优点及适用场景:
        /// 1.需要与SQL Server NEWSEQUENTIALID() 完全兼容和互操作
        /// 2.简单、稳定、社区接受度高    
        /// 3.精度较低(约3.33毫秒)。
        /// PS:建议使用此方案
        /// </summary>
        /// <returns></returns>
        public static Guid NewComb()
        {
            byte[] guidArray = Guid.NewGuid().ToByteArray();

            DateTime baseDate = new DateTime(1900, 1, 1);
            DateTime now = DateTime.Now;

            // 获取从基准时间到现在的毫秒数
            TimeSpan days = new TimeSpan(now.Ticks - baseDate.Ticks);
            TimeSpan msecs = now.TimeOfDay;

            // 转换为字节数组
            byte[] daysArray = BitConverter.GetBytes(days.Days);
            byte[] msecsArray = BitConverter.GetBytes((long)(msecs.TotalMilliseconds / 3.333333));

            // 反转字节顺序,因为 .NET 是小端序
            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(daysArray);
                Array.Reverse(msecsArray);
            }

            // 将时间部分复制到 GUID 中
            Buffer.BlockCopy(daysArray, daysArray.Length - 2, guidArray, guidArray.Length - 6, 2);
            Buffer.BlockCopy(msecsArray, msecsArray.Length - 4, guidArray, guidArray.Length - 4, 4);

            return new Guid(guidArray);
        }

        //使用 MassTransit 的有序 GUID
        /// <summary>
        /// NewId 转换为 GUID 可能不符合 RFC 4122 标准
        /// 高性能要求:选择 MassTransit NewId
        /// </summary>
        /// <returns></returns>
        public static Guid MassGenGuid()
        {
            return MassTransit.NewId.Next().ToGuid();
            // 或者直接使用 NewId 类型
            // Id = NewId.Next().ToString()
        }

    }

 

posted on 2025-11-11 12:10  wakaka_wka  阅读(0)  评论(0)    收藏  举报