凡事涉及到高性能貌似都是高大上的东西,所以嘛我也试试;其实这个时间戳ID的生成主要为了解决我们公司内部的券号生成,估计有小伙伴认为券号生成有这么麻烦嘛,搞个自增ID完全可以用起来,或者时间取毫微米时间戳等。

如果以上真是这样简单的话,那我要说道说道;首先自增ID资源耗尽的时候,特别礼券号生成的越频繁,毕竟bigInt也有耗尽那天(当然如果有更长数字字段就是慢慢耗呗),而且依靠数据库进行被动生成,在有些业务上比较软肋;我还有一个同事说搞一张表定时去自增生成ID,这样就能随时取已经存在的ID资源数据,我只能说这是一种笨办法,而且你都不知道外部业务对券号的需要量有多少,万一立马要个1000万,你来得及?

还有就是毫微米时间戳也是会出问题,因为在多并发请求下也会大概率出现同样ID,大家不信可以去试试,想想我们的CPU运算有多快;当然防止重复可以考虑休眠例如一毫秒,但这样就会丢失性能,想想雪花算法一毫秒能产生4095个不重复ID,我们好歹也可以向它学习吧,以上说了这么多少就明白了这个要求也是蛮苛刻的,当中我也想过用雪花算法,但由于生成的ID比较长(后面我会说为什么不适宜)!

下面来看看我对这个唯一时间戳ID生成的代码算法,借鉴了点雪花算法:

/// <summary>/// 时间戳ID/// </summary>public class TimestampID{private long _lastTimestamp;private long _sequence; //计数从零开始private readonly DateTime? _initialDateTime;private static TimestampID _timestampID;private const int MAX_END_NUMBER = 9999;private TimestampID(DateTime? initialDateTime){_initialDateTime = initialDateTime;}/// <summary>/// 获取单个实例对象/// </summary>/// <param name="initialDateTime">最初时间,与当前时间做个相差取时间戳</param>/// <returns></returns>public static TimestampID GetInstance(DateTime? initialDateTime = null){if (_timestampID == null) Interlocked.CompareExchange(ref _timestampID, new TimestampID(initialDateTime), null);return _timestampID;}/// <summary>/// 最初时间,作用时间戳的相差/// </summary>protected DateTime InitialDateTime{get{if (_initialDateTime == null || _initialDateTime.Value == DateTime.MinValue) return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);return _initialDateTime.Value;}}/// <summary>/// 获取时间戳ID/// </summary>/// <returns></returns>public string GetID(){long temp;var timestamp = GetUniqueTimeStamp(_lastTimestamp, out temp);return $"{timestamp}{Fill(temp)}";//这个时新的C#语法 你可以改为 String.Formate("{0}Fill({1})",timestamp,temp)}private string Fill(long temp){var num = temp.ToString();IList<char> chars = new List<char>();for (int i = 0; i < MAX_END_NUMBER.ToString().Length - num.Length; i++){chars.Add('0');}return new string(chars.ToArray()) + num;}/// <summary>/// 获取一个时间戳字符串/// </summary>/// <returns></returns>public long GetUniqueTimeStamp(long lastTimeStamp, out long temp){lock (this){temp = 1;var timeStamp = GetTimestamp();if (timeStamp == _lastTimestamp){_sequence = _sequence + 1;temp = _sequence;if (temp >= MAX_END_NUMBER){timeStamp = GetTimestamp();_lastTimestamp = timeStamp;temp = _sequence = 1;}}else{_sequence = 1;_lastTimestamp = timeStamp;}return timeStamp;}}/// <summary>/// /// </summary>/// <returns></returns>private long GetTimestamp(){if (InitialDateTime >= DateTime.Now) throw new Exception("最初时间比当前时间还大,不合理");var ts = DateTime.UtcNow - InitialDateTime;return (long)ts.TotalMilliseconds;}}

当中我加了一点补位算法,保证每次出来的ID长度一致,之前提到了是用在礼券号上的,那就应该不能这么长,后续我又继续进行了32进制计算,缩短到8-10位左右,但大家估计觉的还是长,那就看取决你把相差时间应该缩短。但如果直接用雪花算法生成的ID进行32位进制缩短也是在10位以上,所以我没有用到。

对了,忘记说了性能问题,一毫秒预计能生成1000个,呵呵,还算过得去

接下来谈谈礼券这块业务,类似我们初创电商公司这种需要去互联网上大量拉拢会员,所以也相对需要大量的推广礼券号,如果成熟的电商如京东和天猫等,他们所有礼券都已经绑定到自己会员身上,在使用上根本不用去关注填写什么礼券号,也是他们的礼券体系相对完整和成熟,故我们对礼券号的的生成需求也是一块心病。

下面再说说雪花算法生成的ID,比较适合使用一些流水数据,如果分布式上生成时就需要考虑一台吞吐量好的服务统一生成ID,或者也可以进行多台服务器+负载均衡,当然每台机器出的ID还是需要标识补位(比如机器自定义的编号ID)增加长度防止同一时间重复ID。

以上如有不对之处请留言,大家共同学习进步!!!

2017.1.22 > 在生产环境中,突然又发生了礼券号重复问题,导致我怀疑算法的不严谨,后来发现触发生成的来源是两个服务进程,哈哈,真是自己找坑跳;故大家在部署时候一定要确保ID生成在一个进程里,如果分布式还是老话,加上必要的分布标识NO

C# 高并发获取唯一ID算法相关推荐

  1. [Unity][安卓]unity获取唯一ID,游客登陆

    之前做的时候在网上找了好多有现在整理下一个可以用的 代码段如下 在java中编写 public String GetID(){String serial = null;String m_szDevID ...

  2. mysql并发获取唯一数值_高并发分布式环境中获取全局唯一ID[分布式数据库全局唯一主键生成]...

    需求说明 在过去单机系统中,生成唯一ID比较简单,可以使用MySQL的自增主键或者Oracle中的sequence, 在现在的大型高并发分布式系统中,以上策略就会有问题了,因为不同的数据库会部署到不同 ...

  3. 窥探SnowflakeIdWorker之并发生成唯一ID

    2019独角兽企业重金招聘Python工程师标准>>> 订单服务这种流量比较大的服务,可以得知部署的服务器,一般都是几个的,挂了一个还有一个哈,最好让转发请求的服务器,在得知服务挂了 ...

  4. 如何快速开发一个支持高效、高并发的分布式ID生成器(一)

    ID生成器是指能产生不重复ID服务的程序,在后台开发过程中,尤其是分布式服务.微服务程序开发过程中,经常会用到,例如,为用户的每个请求产生一个唯一ID.为每个消息产生一个ID等等,ID生成器也是进行无 ...

  5. id长度 雪花算法_分布式系统中唯一ID算法之雪花算法

    背景 分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的. 有些时候我们希望能使用一种 ...

  6. Android10获取唯一ID最佳做法

    官方文档 安卓Q中Google彻底禁止第三发app获取IMEI,WIFI和蓝牙的MAC地址为:02:00:00:00:00:00. 1.使用实例 ID 和 GUID 对于实例 ID 不实用的情况,您还 ...

  7. 高并发系统--限流算法

    在开发高并发系统时,有三把利器用来保护系统:缓存.降级和限流.通过限流,我们可以很好地控制系统的qps,从而达到保护系统的目的.主要算法有:计数器算法,滑动窗口算法,漏桶算法,令牌桶算法 1.计数器算 ...

  8. MySQL高并发生成唯一订单号的方法

    高并发下生成唯一订单号的存储过程 这个是用mysql写的存储过程,搭配里面一张数据表使用,达到高并发情况下获得唯一订单号的目的:原理:按照一定规则生成订单号后,把订单号插入数据表后,再返回给用户,由于 ...

  9. android 获取唯一Id,小小总结一下。仅供参考

    1.获取imei: 前言: 因传统的移动终端设备标识如国际移动设备识别码(IMEI)等已被部分国家认定为用户隐私的一部分, 并存在被篡改和冒用的风险,所以在Android 10及后续版本中非厂商系统应 ...

最新文章

  1. 博士申请 | ​香港中文大学LaVi实验室招收2022年秋季入学博士生、硕士生
  2. android 驻留广播,Android实现Service永久驻留
  3. 下载Java Jar包的网站(托管厂库)
  4. 计算机视觉:基于眼疾分类数据集iChallenge-PM图像分类经典模型剖析(LeNet,AlexNet,VGG,GoogLeNet,ResNet)
  5. php简单文件上传类
  6. 5.5.2 最小的N个和
  7. IplImage结构及与其相关的读写函数
  8. 信息系统分析与设计相关
  9. 家庭医生后台管理系统高保真Axure原型模板
  10. 一个关于创业不错的博客
  11. 【软件测试】公司招个测试员,我又面试了100多人,结局......
  12. (三十六)Delta中性对冲与Delta-Gamma中性对冲
  13. android远程控制win10,微软推出适用于Win10专业版的Android远程控制
  14. Scratch学习:如何把角色设置成半透明?
  15. 数据治理-1. 数据集成-总体方案
  16. csv文件和excel文件
  17. 每日三省吾身,省什么?
  18. 干货| 三大软件架构对比与分析
  19. CSS——文字对齐方式
  20. php 修改include文件,PHP Include 文件

热门文章

  1. 大学计算机基础教学目标,大学计算机基础教学大纲2015.doc
  2. (1)在ensp上面进行静态路由和默认路由测试(直接上手)
  3. Mysql生成UUID 亲测
  4. 常用crc查表法_请教查表法计算CRC的原理
  5. Sklearn上机笔记--标准化
  6. 知识图谱从入门到应用——知识图谱的应用
  7. 9行代码用python制作迷宫gif动画
  8. 解决Photoshop CS3 输入中文不能显示 输入文字不能显示 输入文字显示缓慢
  9. Python 设计模式 - 建造者模式
  10. 大使、布道师、贡献者,OpenHarmony社区发起三大贡献者激励计划