【高性能】生成唯一时间戳ID,1毫秒预计能生成1000个
凡事涉及到高性能貌似都是高大上的东西,所以嘛我也试试;其实这个时间戳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(, , , , , , 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)}";
} private string Fill(long temp)
{
var num = temp.ToString();
IList<char> chars = new List<char>();
for (int i = ; i < MAX_END_NUMBER.ToString().Length - num.Length; i++)
{
chars.Add('');
}
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 + ;
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
【高性能】生成唯一时间戳ID,1毫秒预计能生成1000个的更多相关文章
- 生成唯一的id(转)
很多朋友都利用md5()来生成唯一的编号,但是md5()有几个缺点:1.无序,导致数据库中排序性能下降.2.太长,需要更多的存储空间.其实PHP中自带一个函数来生成唯一的id,这个函数就是uniqid ...
- js生成唯一的id
1.生成[0,1)的随机数的Math.random Math.random().toString().replace(".", "");// 生成唯一的id 2 ...
- 据时间生成唯一序列ID
据时间生成唯一序列ID /** * <html> * <body> * <P> Copyright 1994 JsonInternational</p> ...
- C#生成唯一的ID保存到数据库
直接用.NET Framework 提供的 Guid() 函数: Guid.NewGuid()是指生成唯一码的规则 System.Guid.NewGuid().ToString()全球唯一标识符 (G ...
- java生成唯一的id编号
GUID是一个128位长的数字,一般用16进制表示.算法的核心思想是结合机器的网卡.当地时间.一个随即数来生成GUID.从理论上讲,如果一台机器每秒产生10000000个GUID,则可以保证(概率意义 ...
- 生成唯一的ID
public class UniqueId { public static String getUUId(){ ; int hashCodeV = UUID.randomUUID().toString ...
- Java生成唯一的ID
public class UIDGenerator { private static Date date = new Date(); private static StringBuilder buf ...
- js 如何生成唯一且不可预测的 ID
通常数据库可以生成唯一的 ID,最多的就是数字序列,也有像 MongoDB 这样产生组合序列的,不过这种形式的 ID 由于是序列,是可以预测的.如果想得到不可预测且唯一的 ID,方法还是有的. 下面主 ...
- 如何使用php生成唯一ID的4种方法
php生成唯一ID的应用场景非常普遍,如临时缓存文件名称,临时变量,临时安全码等,uniqid()函数基于以微秒计的当前时间,生成一个唯一的 ID.由于生成唯一ID与微秒时间关联,因此ID的唯一性非常 ...
随机推荐
- Unity3d在线游戏Socket通讯
网络游戏是一个人的互动娱乐软件应用.因为它是交互式,当然,需要了解对方的通信.这需要通信Socket:我们今天要实现的主角即套接字.Socket的英文原义是"孔"或"插座 ...
- Spring Resource之ResourceLoaderAware接口
ResourceLoaderAware接口是一个特殊的标记接口,它表示对象需要提供给一个ResourceLoader引用: public interface ResourceLoaderAware { ...
- [转]Mysql explain用法和性能分析
本文转自:http://blog.csdn.net/haifu_xu/article/details/16864933 from @幸福男孩 MySQL中EXPLAIN解释命令是显示mysql如何 ...
- 大约Android 3.0后AsyncTask默认的单线程分析
在Android下了很大的后台操作在需要的情况下.通常用于AsyncTask这个类.比方说,网络负载形象.访问server接口.一般的情况是使用一个的一例AsyncTask对象mTask,复制Asyn ...
- leetcode第40题--First Missing Positive
题目: Given an unsorted integer array, find the first missing positive integer. For example,Given [1,2 ...
- 【DateTime格式大全
】
DateTime dt = DateTime.Now;// Label1.Text = dt.ToString();//2005-11-5 13:21:25// Label2.Text = ...
- 【转】GitHub 优秀的 Android 开源项目
转自:http://blog.csdn.net/shulianghan/article/details/18046021 主要介绍那些不错个性化的View,包括ListView.ActionBar.M ...
- CSS3中文手册基础知识
CSS3手册是学习CSS3的最佳文档,不管是自己写博客,还是买书,手册少不了.今天我给大家介绍一些CSS3有哪些分类及其使用. 具体参考:http://caibaojian.com/css3/ 上来进 ...
- HTML5 CANVAS制图 基础总结
一.基本绘图 首先,定义2D渲染变量ct(这里用了Jquery库): var ct = $(#canvasId).get(0).getContext('2d'); 以下是绘制各种基本图形的方法: // ...
- MVC 5 - 将数据从控制器传递给视图
MVC 5 - 将数据从控制器传递给视图 在我们讨论数据库和数据模型之前,让我们先讨论一下如何将数据从控制器传递给视图.控制器类将响应请求来的URL.控制器类是给您写代码来处理传入请求的地方,并从数据 ...