.net 同一时间戳下生成不重复的订单标识
为了避免在业务中出现订单号重复的情况,这里针对生产订单号的方法做了一定优化,基本可以避免同一时间戳下生成重复标识的问题。
思路: 假设订单编号由 平台标识(4位)+ 年份(4位) + 时间戳(10位) + 随机数(4位)组成的22位订单编号,由于前面8位固定的,
如果我们想要避免重复,就要避免 同一时间戳下生成重复的随机数。
代码如下
private static readonly object _lock = new object(); private static Dictionary<string, List<int>> _dic = new Dictionary<string, List<int>>(); private static long _num; /// <summary> /// 生成唯一平台订单号 /// </summary> /// <param name="ctype"></param> /// <returns></returns> public static string GeneratOrderNo(ContractType ctype) { lock (_lock) { TimeSpan timespan = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); string timeStamp = Convert.ToInt64(timespan.TotalSeconds).ToString(); //若时间戳 + 随机数重复, 重新生成随机数 string nonce = GenerateNonce(timeStamp); return ((int)ctype).ToString() + DateTime.Now.ToString("yyyy") + timeStamp + nonce; } } /// <summary> /// 生成不重复的四位随机数(同一时间戳下不允许重复) /// </summary> /// <param name="timeStamp">10位时间戳</param> /// <returns></returns> private static string GenerateNonce(string timeStamp) { Random random = new Random(RandomHelper.GetRandomSeed()); int nonce = random.Next(1000, 9999); if (_dic.TryGetValue(timeStamp, out List<int> value)) { //重新获取随机数 if (value.Contains(nonce)) { return GenerateNonce(timeStamp); } else { value.Add(nonce); _dic.Remove(timeStamp); _dic.Add(timeStamp, value); } } else { _dic.Clear(); _dic.Add(timeStamp, new List<int> { nonce }); } return nonce.ToString(); }
定义 lock 变量,可确保当一个线程位于代码的临界区时,另一个线程不会进入该临界区。
定义 _dic 变量,用键值对的方式存储时间戳 + 随机数(nonce),以时间戳 timeStamp 作 Key , 并保存同一时间戳 timeStamp 下的所有随机数集合,作为键值。
若为同一时间戳下生成的订单号,获取到已存的随机数集合进行匹配,如果重复则重新生成新的随机数 nonce,确保不会出现重复值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | static void Test() { string orderId = "" ; //创建包含两个线程的数组 TaskFactory factory = new TaskFactory(); Task[] tasks = new Task[] { factory.StartNew( new Action(GenerateId)), factory.StartNew(()=> GenerateId()) }; Task.WaitAll(tasks); Console.WriteLine(orderId); } private static void GenerateId() { for ( var i = 0; i < 100; i++) { orderId += GeneratOrderNo(ContractType.Tag) + System.Environment.NewLine; } orderId += "--------------------------------" + System.Environment.NewLine; } |
另附上生成二十位随机数【10时间戳 + 10位递增值】的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | /// <summary> /// 根据时间戳生成20位编号 /// </summary> /// <returns></returns> public static string GenerateId() { lock (_lock) //lock 关键字可确保当一个线程位于代码的临界区时,另一个线程不会进入该临界区。 { if (_num == int .MaxValue) { _num = 0; } else { _num++; } TimeSpan timespan = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); string timeStamp = Convert.ToInt64(timespan.TotalSeconds).ToString(); Thread.Sleep(10); return timeStamp + _num.ToString().PadLeft(10, '0' ); } } |
分类:
.net 基础篇
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现