如何在asp.net 时间戳下生成18位时间戳

温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
每天进步一点点
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
来源:/binSelect/archive//2642318.html1 将系统时间转换成UNIX时间戳DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970,1,1));
DateTime dtNow = DateTime.Parse(DateTime.Now.ToString());
TimeSpan toNow = dtNow.Subtract(dtStart);
string timeStamp = toNow.Ticks.ToString();
timeStamp = timeStamp.Substring(0,timeStamp.Length - 7);&&&2将UNIX时间戳转换成系统时间string timeStamp = "";
DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970,1,1));
long lTime = long.Parse(timeStamp + "0000000");
TimeSpan toNow = new TimeSpan(lTime);
DateTime dtResult = dtStart.Add(toNow);
阅读(239)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
在LOFTER的更多文章
loftPermalink:'',
id:'fks_',
blogTitle:'UNIX时间戳与asp.net日期的转换',
blogAbstract:'来源:/binSelect/archive//2642318.html1 将系统时间转换成UNIX时间戳',
blogTag:'',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:0,
publishTime:5,
permalink:'blog/static/',
commentCount:0,
mainCommentCount:0,
recommendCount:0,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:true,
hostIntro:'每天进步一点点',
hmcon:'1',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}在ASP.NET程序中创建唯一序号
如果在程序中需要创建全局唯一的序号,那么必须对创建序号的过程进行同步处理,防止多个并发访问时出现相同序号的情况。下面列出几种方法供大家参考。
利用数据库的方法
后面的例子都基于MS SQL Server,如果使用Oracle可以直接读取Sequence对象,则不需要进行如此复杂的操作。
方法1:利用表锁定
create table xtab (seq_id int primary key, create_time datetime)
存储过程或SQL语句:
以下为引用的内容:begin tran
declare @max_seq int
--读出记录时锁定表
select @max_seq=max(seq_id) from xtab with (TABLOCKX)
set @max_seq = isnull(@max_seq,0)
set @max_seq = @max_seq+1
print @max_seq
insert into xtab values(@max_seq,getDate())
--变量@max_seq 中存放的就是当前产生的序号
方法2:利用自增字段
如果利用自增变量可以通过方法1中锁定表,然后再插入记录,并读取最大值的方法。不过下面讲的是通过C#的ADO.NET来插入记录,并读取已经插入的记录的自增字段。
create table xtab_i (seq_id int IDENTITY(1,1) primary key, create_time datetime)
C#代码,利用时间处理函数在数据被更新时同时读取@@IDENTITY变量的值。完整内容参考:OleDbWrap.cs 文件。
以下为引用的内容://参数内容://szSelectSql = &select * from xtab_i where seq_id isnull&;//szTabName = &xtab_i&;/// &summary&/// 通过查询语句 创建DataSet对象,返回的对象用于执行插入操作/// &/summary&/// &param name=&szSelectSql&&SQL语句&/param&/// &param name=&szTabName&&表名称&/param&/// &returns&用于插入的DataSet对象&/returns&
public DataSet CreateInsertDataSet_bySelect(string szSelectSql,string szTabName){      m_dbAdapter.SelectCommand = new OleDbCommand(szSelectSql, m_dbConn); OleDbCommandBuilder cb = new OleDbCommandBuilder(m_dbAdapter); DataSet ds = new DataSet(); m_dbAdapter.Fill(ds, szTabName); m_dbAdapter.RowUpdated += new OleDbRowUpdatedEventHandler(OnRowUpdated_Inserted); }//----------------私有事件处理/// &summary&/// 处理数据插入的更新事件/// &/summary&/// &param name=&sender&&&/param&/// &param name=&args&&&/param&
protected void OnRowUpdated_Inserted(object sender, OleDbRowUpdatedEventArgs args){ OleDbCommand idCMD = new OleDbCommand(&SELECT @@IDENTITY&, m_dbConn); if (args.StatementType == StatementType.Insert)  {  object rObj = idCMD.ExecuteScalar();   if(rObj == null) m_iDbIdentity =-1;  else if( rObj.ToString() !=&&)    m_iDbIdentity = Int32.Parse(rObj.ToString());   else   m_iDbIdentity =-1;  } idCMD.Dispose();  //m_iDbIdentity变量中包含的就是当前插入列的自增字段的值}
利用程序控制
方法1:利用ASP.NET中的Application对象
利用ASP.NET中的全局HttpApplicationState对象。
Application.Lock();
Application[&xlock&]=&locked&;
{ //必须捕捉异常,避免无法解锁对象
//your Code here
catch (Exception e)
Application[&xlock&]=&unlock&;
方法2:利用操作系统中的同步对象来实现同步
在dotNet的框架的System.Threading命名空间下定义了多种用于同步的类,例如:Mutex,Semaphore。下面介绍一下利用互斥对象Mutex来实现同步的方法。
以下为引用的内容:void Test(){ //需要引入 System.T//创建名为MyMutex的互斥对象,如果OS已经创建过同名对象则只是重新获得句柄
Mutex m = new Mutex(false, &MyMutex&);//在10秒内等待取得访问权boolean getMutex=m.WaitOne(10*1000,false);if(getMutex){ //已经取得访问权 try {  //必须捕捉异常,避免无法解锁对象  //Your code here } catch(Exception e) { } m.ReleaseMutex();}else{ //没有取得访问权}
在程序中应该尽量使用Mutex这类可以命名的同步对象以达到创建多个同步对象,对多种资源进行同步的目的。如果要实现多个同入可以使用信号量 Semaphore。
其他方法:利用lock关键字防止线程并发同一段代码执行
以下为引用的内容:class CTest {  void Increase()  {  lock (this)  {   balance++;  } }}
由于ASP.NET程序在IIS中可能配置不同的线程模式,所以在ASP.NET程序尽可能不要使用这种方法同步线程,而在普通的应用程序中是可以使用这种方法。
&附:OleDbWrap.cs ,是一个很简单的封装类,封装了基本的数据库操作。
以下为引用的内容:using Susing System.Dusing System.Data.OleDb;
namespace Wyy.Wrap{/// &summary&/// wDbWrap 说明:完成数据库访问功能/// 1 创建Connection,Adapter,管理对象内的Conn和Adapter对象/// 2 通过Select结果集填充Dataset/// 3 插入/// 4 更新/// &/summary&public class OleDbWrap{//--------公共方法/// &summary&/// 在对象被清除时会自动清除 数据库连接对象/// &/summary&public OleDbWrap(){m_dbConn = new OleDbConnection(DbString);m_fAutoDelConn =m_dbAdapter = new OleDbDataAdapter();m_dbConn.Open();}/// &summary&/// 通过连接字符串构造内部的数据库连接对象/// &/summary&/// &param name=&strConnection&&ADO连接字符串&/param&public OleDbWrap(string strConnection){m_dbConn = new OleDbConnection(strConnection);m_fAutoDelConn =m_dbAdapter = new OleDbDataAdapter();m_dbConn.Open();}/// &summary&/// 通过现有连接构造对象,在对象被清除时不会自动清除 数据库连接对象/// &/summary&/// &param name=&conn&&现存的数据库连接对象&/param&public OleDbWrap(OleDbConnection conn){m_dbConn =m_fAutoDelConn =m_dbAdapter = new OleDbDataAdapter();//m_dbConn.Open();}public virtual void Dispose(){m_dbAdapter.Dispose();if(m_fAutoDelConn){m_dbConn.Close();m_dbConn.Dispose();}}/// &summary&/// 通过SQL语句创建DataReader对象/// &/summary&/// &param name=&szSql&&SQL语句&/param&/// &returns&DataReader对象&/returns&public OleDbDataReader CreateDataReader(string szSql){OleDbCommand cmd = new OleDbCommand(szSql,m_dbConn);OleDbDataReader dr= cmd.ExecuteReader();cmd.Dispose();}/// &summary&/// 通过SQL查询语句,返回第一行结果,可以用于执行类似与Select Count(*)的语句/// &/summary&/// &param name=&szSql&&SQL语句&/param&/// &returns&返回对象&/returns&public object ExecuteScalar(string szSql){OleDbCommand idCMD = new OleDbCommand(szSql, m_dbConn);object rObj = idCMD.ExecuteScalar();idCMD.Dispose();return rO}/// &summary&/// 调用OleDbCommand 的 ExecuteNonQuery/// &/summary&/// &param name=&szSql&&&/param&/// &returns&&/returns&public int ExecuteNonQuery(string szSql){OleDbCommand idCMD = new OleDbCommand(szSql, m_dbConn);int iRet = idCMD.ExecuteNonQuery();idCMD.Dispose();return iR}/// &summary&/// 创建查询用DataSet对象/// &/summary&/// &param name=&szSql&&查询SQL语句&/param&/// &param name=&szTabName&&表名称&/param&/// &returns&已经被填充的DataSet对象&/returns&public DataSet CreateSelectDataSet(string szSql,string szTabName){m_dbAdapter.SelectCommand = new OleDbCommand(szSql,m_dbConn);DataSet ds = new DataSet();m_dbAdapter.Fill(ds,szTabName);}/// &summary&/// 通过查询语句 创建DataSet对象,返回的对象用于执行插入操作/// &/summary&/// &param name=&szSelectSql&&SQL语句&/param&/// &param name=&szTabName&&表名称&/param&/// &returns&用于插入的DataSet对象&/returns&public DataSet CreateInsertDataSet_bySelect(string szSelectSql,string szTabName){m_dbAdapter.SelectCommand = new OleDbCommand(szSelectSql, m_dbConn);
OleDbCommandBuilder cb = new OleDbCommandBuilder(m_dbAdapter);
DataSet ds = new DataSet();m_dbAdapter.Fill(ds, szTabName);m_dbAdapter.RowUpdated += new OleDbRowUpdatedEventHandler(OnRowUpdated_Inserted);}/// &summary&/// 通过查询语句 创建DataSet对象,返回的对象用于执行更新操作/// &/summary&/// &param name=&szSelectSql&&SQL语句&/param&/// &param name=&szTabName&&表名称&/param&/// &returns&用于更新的DataSet对象&/returns&public DataSet CreateUpdateDataSet_bySelect(string szSelectSql,string szTabName){m_dbAdapter.SelectCommand = new OleDbCommand(szSelectSql, m_dbConn);
OleDbCommandBuilder cb = new OleDbCommandBuilder(m_dbAdapter);
DataSet ds = new DataSet();m_dbAdapter.Fill(ds, szTabName);//m_dbAdapter.RowUpdated += new OleDbRowUpdatedEventHandler(OnRowUpdated_Update);}//----------------私有事件处理/// &summary&/// 处理数据插入的更新事件/// &/summary&/// &param name=&sender&&&/param&/// &param name=&args&&&/param&protected void OnRowUpdated_Inserted(object sender, OleDbRowUpdatedEventArgs args){OleDbCommand idCMD = new OleDbCommand(&SELECT @@IDENTITY&, m_dbConn);
if (args.StatementType == StatementType.Insert){object rObj = idCMD.ExecuteScalar();if(rObj == null)m_iDbIdentity =-1;else if( rObj.ToString() !=&&)m_iDbIdentity = Int32.Parse(rObj.ToString());elsem_iDbIdentity =-1;}idCMD.Dispose();}//------------公共属性/// &summary&/// 在插入数据后获取新数据行中自增字段的值,目前只能支持一个自增字段/// &/summary&public Int32 DbIdentity {get{return m_iDbI} }/// &summary&/// 数据库连接字符串,保存在web.config文件中 &appSettings&节/// &/summary&public string DbString {get{return System.Configuration.ConfigurationSettings.AppSettings[&dbStr&];}}
//------------公共变量/// &summary&/// 数据库连接/// &/summary&public OleDbConnection m_dbC/// &summary&/// 查询Adapter/// &/summary&public OleDbDataAdapter m_dbApublic const String m_szRootUrl =&/copathway/toDo/&;
//---------- 私有变量/// &summary&/// 保存数据库插入是自增字段的值/// &/summary&protected Int32 m_iDbIdentity =-1;protected bool m_fAutoDelConn =}}
最新图文推荐
最新专栏文章
大家感兴趣的内容
&&<a rel="nofollow" class="red" href="" target="_blank" color="red新版网站排行榜
===全新上线===
网友热评的文章
seajs.config({
base: "/resource/passapi/scripts/"
seajs.use('seajs/seajs-css');
seajs.use(['artdialog/src/dialog-plus'], function (dialog) {
$('#favorite').on('click', function(){
$.getJSON('/passapi.ashx?op=userstatus&callback=?', function(data){
if (data.status == 1) {
var _this = $('#favorite').find('span');
$.getJSON('/?app=favorite&controller=favorite&action=add&jsoncallback=?&contentid='+contentid, function(json){
if(json.state){
_this.html('温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
阅读(294)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
loftPermalink:'',
id:'fks_',
blogTitle:'[ASP.NET] 时间戳问题',
blogAbstract:'对于文件上传,或者EXCEL数据上传的同时上传EXCEL文件备份,需要用到时间戳命名,以便于查找。string newfilename = DateTime.Now.ToString(\"yyyyMMddHHmmssfff\");注意MM和HH需要大写,都在显示的数据讲不是你需要的。下面是百度到的(供参考,未测试,感觉不是想要的)://获取日期+时间DateTime.Now.ToString();
20:02:10DateTime.Now.ToLocalTime().ToString();
20:12:12 //获取日期',
blogTag:'asp.net',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:5,
publishTime:2,
permalink:'blog/static/',
commentCount:0,
mainCommentCount:0,
recommendCount:0,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'',
hmcon:'1',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}分布式系统唯一ID生成方案汇总_asp.net开发_ThinkSAAS
分布式系统唯一ID生成方案汇总
分布式系统唯一ID生成方案汇总
来自: &#13;
系统唯一ID是我们在设计一个系统的时候常常会遇见的问题,也常常为这个问题而纠结。生成ID的方法有很多,适应不同的场景、需求以及性能要求。所以有些比较复杂的系统会有多个ID生成的策略。下面就介绍一些常见的ID生成策略。&#13;
1. 数据库自增长序列或字段&#13;
最常见的方式。利用数据库,全数据库唯一。&#13;
优点:&#13;
1)简单,代码方便,性能可以接受。&#13;
2)数字ID天然排序,对分页或者需要排序的结果很有帮助。&#13;
缺点:&#13;
1)不同数据库语法和实现不同,数据库迁移的时候或多数据库版本支持的时候需要处理。&#13;
2)在单个数据库或读写分离或一主多从的情况下,只有一个主库可以生成。有单点故障的风险。&#13;
3)在性能达不到要求的情况下,比较难于扩展。&#13;
4)如果遇见多个系统需要合并或者涉及到数据迁移会相当痛苦。&#13;
5)分表分库的时候会有麻烦。&#13;
优化方案:&#13;
1)针对主库单点,如果有多个Master库,则每个Master库设置的起始数字不一样,步长一样,可以是Master的个数。比如:Master1 生成的是 1,4,7,10,Master2生成的是2,5,8,11 Master3生成的是 3,6,9,12。这样就可以有效生成集群中的唯一ID,也可以大大降低ID生成数据库操作的负载。&#13;
2. UUID&#13;
常见的方式。可以利用数据库也可以利用程序生成,一般来说全球唯一。&#13;
优点:&#13;
1)简单,代码方便。&#13;
2)生成ID性能非常好,基本不会有性能问题。&#13;
3)全球唯一,在遇见数据迁移,系统数据合并,或者数据库变更等情况下,可以从容应对。&#13;
缺点:&#13;
1)没有排序,无法保证趋势递增。&#13;
2)UUID往往是使用字符串存储,查询的效率比较低。&#13;
3)存储空间比较大,如果是海量数据库,就需要考虑存储量的问题。&#13;
4)传输数据量大&#13;
5)不可读。&#13;
3. UUID的变种&#13;
1)为了解决UUID不可读,可以使用UUID to Int64的方法。及&#13;
/// &summary&&#13;
/// 根据GUID获取唯一数字序列&#13;
/// &/summary&&#13;
public static long GuidToInt64()&#13;
byte[] bytes = Guid.NewGuid().ToByteArray();&#13;
return BitConverter.ToInt64(bytes, 0);&#13;
} 2)为了解决UUID无序的问题,NHibernate在其主键生成方式中提供了Comb算法(combined guid/timestamp)。保留GUID的10个字节,用另6个字节表示GUID生成的时间(DateTime)。&#13;
/// &summary& &#13;
/// Generate a new &see cref="Guid"/& using the comb algorithm. &#13;
/// &/summary& &#13;
private Guid GenerateComb()&#13;
byte[] guidArray = Guid.NewGuid().ToByteArray();&#13;
DateTime baseDate = new DateTime();&#13;
DateTime now = DateTime.N&#13;
// Get the days and milliseconds which will be used to build
//the byte string
TimeSpan days = new TimeSpan(now.Ticks - baseDate.Ticks);&#13;
TimeSpan msecs = now.TimeOfD&#13;
// Convert to a byte array
// Note that SQL Server is accurate to 1/300th of a
// millisecond so we divide by 3.333333
byte[] daysArray = BitConverter.GetBytes(days.Days);&#13;
byte[] msecsArray = BitConverter.GetBytes((long)&#13;
(msecs.TotalMilliseconds / 3.333333));&#13;
// Reverse the bytes to match SQL Servers ordering
Array.Reverse(daysArray);&#13;
Array.Reverse(msecsArray);&#13;
// Copy the bytes into the guid
Array.Copy(daysArray, daysArray.Length - 2, guidArray,&#13;
guidArray.Length - 6, 2);&#13;
Array.Copy(msecsArray, msecsArray.Length - 4, guidArray,&#13;
guidArray.Length - 4, 4);&#13;
return new Guid(guidArray);&#13;
} 用上面的算法测试一下,得到如下的结果:作为比较,前面3个是使用COMB算法得出的结果,最后12个字符串是时间序(统一毫秒生成的3个UUID),过段时间如果再次生成,则12个字符串会比图示的要大。后面3个是直接生成的GUID。&#13;
如果想把时间序放在前面,可以生成后改变12个字符串的位置,也可以修改算法类的最后两个Array.Copy。&#13;
4. Redis生成ID&#13;
当使用数据库来生成ID性能不够要求的时候,我们可以尝试使用Redis来生成ID。这主要依赖于Redis是单线程的,所以也可以用生成全局唯一的ID。可以用Redis的原子操作 INCR和INCRBY来实现。&#13;
可以使用Redis集群来获取更高的吞吐量。假如一个集群中有5台Redis。可以初始化每台Redis的值分别是1,2,3,4,5,然后步长都是5。各个Redis生成的ID为:&#13;
A:1,6,11,16,21&#13;
B:2,7,12,17,22&#13;
C:3,8,13,18,23&#13;
D:4,9,14,19,24&#13;
E:5,10,15,20,25&#13;
这个,随便负载到哪个机确定好,未来很难做修改。但是3-5台服务器基本能够满足器上,都可以获得不同的ID。但是步长和初始值一定需要事先需要了。使用Redis集群也可以方式单点故障的问题。&#13;
另外,比较适合使用Redis来生成每天从0开始的流水号。比如订单号=日期+当日自增长号。可以每天在Redis中生成一个Key,使用INCR进行累加。&#13;
优点:&#13;
1)不依赖于数据库,灵活方便,且性能优于数据库。&#13;
2)数字ID天然排序,对分页或者需要排序的结果很有帮助。&#13;
缺点:&#13;
1)如果系统中没有Redis,还需要引入新的组件,增加系统复杂度。&#13;
2)需要编码和配置的工作量比较大。&#13;
5. Twitter的snowflake算法&#13;
snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。具体实现的代码可以参看
C#代码如下:&#13;
/// &summary&&#13;
/// From: /twitter/snowflake&#13;
/// An object that generates IDs.&#13;
/// This is broken into a separate class in case&#13;
/// we ever want to support multiple worker threads&#13;
/// per process&#13;
/// &/summary&&#13;
public class IdWorker&#13;
private long workerId;&#13;
private long datacenterId;&#13;
private long sequence = 0L;&#13;
private static long twepoch = 7L;&#13;
private static long workerIdBits = 5L;&#13;
private static long datacenterIdBits = 5L;&#13;
private static long maxWorkerId = -1L ^ (-1L && (int)workerIdBits);&#13;
private static long maxDatacenterId = -1L ^ (-1L && (int)datacenterIdBits);&#13;
private static long sequenceBits = 12L;&#13;
private long workerIdShift = sequenceB&#13;
private long datacenterIdShift = sequenceBits + workerIdB&#13;
private long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdB&#13;
private long sequenceMask = -1L ^ (-1L && (int)sequenceBits);&#13;
private long lastTimestamp = -1L;&#13;
private static object syncRoot = new object();&#13;
public IdWorker(long workerId, long datacenterId)&#13;
// sanity check for workerId&#13;
if (workerId & maxWorkerId || workerId & 0)&#13;
throw new ArgumentException(string.Format("worker Id can&t be greater than %d or less than 0", maxWorkerId));&#13;
if (datacenterId & maxDatacenterId || datacenterId & 0)&#13;
throw new ArgumentException(string.Format("datacenter Id can&t be greater than %d or less than 0", maxDatacenterId));&#13;
this.workerId = workerId;&#13;
this.datacenterId = datacenterId;&#13;
public long nextId()&#13;
lock (syncRoot)&#13;
long timestamp = timeGen();&#13;
if (timestamp & lastTimestamp)&#13;
throw new ApplicationException(string.Format("Clock moved backwards.
Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));&#13;
if (lastTimestamp == timestamp)&#13;
sequence = (sequence + 1) & sequenceM&#13;
if (sequence == 0)&#13;
timestamp = tilNextMillis(lastTimestamp);&#13;
sequence = 0L;&#13;
lastTimestamp =&#13;
return ((timestamp - twepoch) && (int)timestampLeftShift) | (datacenterId && (int)datacenterIdShift) | (workerId && (int)workerIdShift) |&#13;
protected long tilNextMillis(long lastTimestamp)&#13;
long timestamp = timeGen();&#13;
while (timestamp &= lastTimestamp)&#13;
timestamp = timeGen();&#13;
protected long timeGen()&#13;
return (long)(DateTime.UtcNow - new DateTime(, 0, 0, 0, DateTimeKind.Utc)).TotalM&#13;
} 测试代码如下:&#13;
private static void TestIdWorker()&#13;
HashSet&long& set = new HashSet&long&();&#13;
IdWorker idWorker1 = new IdWorker(0, 0);&#13;
IdWorker idWorker2 = new IdWorker(1, 0);&#13;
Thread t1 = new Thread(() =& DoTestIdWoker(idWorker1, set));&#13;
Thread t2 = new Thread(() =& DoTestIdWoker(idWorker2, set));&#13;
t1.IsBackground =&#13;
t2.IsBackground =&#13;
t1.Start();&#13;
t2.Start();&#13;
Thread.Sleep(30000);&#13;
t1.Abort();&#13;
t2.Abort();&#13;
catch (Exception e)&#13;
Console.WriteLine("done");&#13;
private static void DoTestIdWoker(IdWorker idWorker, HashSet&long& set)&#13;
while (true)&#13;
long id = idWorker.nextId();&#13;
if (!set.Add(id))&#13;
Console.WriteLine("duplicate:" + id);&#13;
Thread.Sleep(1);&#13;
} snowflake算法可以根据自身项目的需要进行一定的修改。比如估算未来的数据中心个数,每个数据中心的机器数以及统一毫秒可以能的并发数来调整在算法中所需要的bit数。&#13;
优点:&#13;
1)不依赖于数据库,灵活方便,且性能优于数据库。&#13;
2)ID按照时间在单机上是递增的。&#13;
缺点:&#13;
1)在单机上是递增的,但是由于涉及到分布式环境,每台机器上的时钟不可能完全同步,也许有时候也会出现不是全局递增的情况。&#13;
6. 利用zookeeper生成唯一ID&#13;
zookeeper主要通过其znode数据版本来生成序列号,可以生成32位和64位的数据版本号,客户端可以使用这个版本号来作为唯一的序列号。很少会使用zookeeper来生成唯一ID。主要是由于需要依赖zookeeper,并且是多步调用API,如果在竞争较大的情况下,需要考虑使用分布式锁。因此,性能在高并发的分布式环境下,也不甚理想。7. MongoDB的ObjectIdMongoDB的ObjectId和snowflake算法类似。它设计成轻量型的,不同的机器都能用全局唯一的同种方法方便地生成它。MongoDB 从一开始就设计用来作为分布式数据库,处理多个节点是一个核心要求。使其在分片环境中要容易生成得多。 其格式如下:&#13;
前4 个字节是从标准纪元开始的时间戳,单位为秒。时间戳,与随后的5 个字节组合起来,提供了秒级别的唯一性。由于时间戳在前,这意味着ObjectId 大致会按照插入的顺序排列。这对于某些方面很有用,如将其作为索引提高效率。这4 个字节也隐含了文档创建的时间。绝大多数客户端类库都会公开一个方法从ObjectId 获取这个信息。&#13;
接下来的3 字节是所在主机的唯一标识符。通常是机器主机名的散列值。这样就可以确保不同主机生成不同的ObjectId,不产生冲突。&#13;
为了确保在同一台机器上并发的多个进程产生的ObjectId 是唯一的,接下来的两字节来自产生ObjectId 的进程标识符(PID)。&#13;
前9 字节保证了同一秒钟不同机器不同进程产生的ObjectId 是唯一的。后3 字节就是一个自动增加的计数器,确保相同进程同一秒产生的ObjectId 也是不一样的。同一秒钟最多允许每个进程拥有 216)个不同的ObjectId。&#13;
实现的源码可以到MongoDB官方网站下载。&#13;
PHP开发框架
开发工具/编程工具
服务器环境
ThinkSAAS商业授权:
ThinkSAAS为用户提供有偿个性定制开发服务
ThinkSAAS将为商业授权用户提供二次开发指导和技术支持
让ThinkSAAS更好,把建议拿来。
开发客服微信

我要回帖

更多关于 asp.net 获取时间戳 的文章

 

随机推荐