这篇文章主要讲解了。”网络核心中如何反解ObjectId”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习”。网络核心中如何反解ObjectId”吧!
<强>前言强>
在设计数据库的时候,我们通常需要给业务数据表分配主键,很多时候,为了省的事,我都是直接使用GUID/UUID的方式,但是在MonggoDB中,其内部实现了ObjectId(以下统称为Oid)。并且在。NETCore的驱动中给出了源代码的实现。
经过仔细研读官方的源码后发现,其实现原理非常的简单易学,在最新的版本中,阉割了解压函数,可能是官方觉得解包是没什么太多的使用场景的,但是我们认为,对于数据溯源来说,解包的操作实在是非常有必要,特别是在目前的微服务大流行的背景下。
为此,在参考官方代码的基础上进行了部分改进,增加了一下自己的需求。本示例代码增加了解包的操作,对字符串的隐式转换,提供读取解包后数据的公开属性。
<强> ObjectId的数据结构强>
首先,我们来看Oid的数据结构的设计。
从上图可以看出,Oid的数据结构主要由四个部分组成,分别是:Unix时间戳,机器名称,进程编号,自增编号.Oid实际上是总长度为12个字节24的字符串,易记口诀为:4323年,时间4字节,机器名3字节,进程编2号字节,自增编3号字节。
1, Unix时间戳:Unix时间戳以秒为记录单位,即从1970/1/1就是开始到当前时间的总秒数。
2,机器名称:记录当前生产Oid的设备号
3,进程编号:当前运行Oid程序的编号
4,自增编号:在当前秒内,每次调用都将自动增长(已实现线程安全)
根据算法可知,当前一秒内产生的最大id数量为2 ^ 24=16777216条记录,所以无需过多担心id碰撞的问题。
<强>实现思路强>
先来看一下代码实现后的类结构图。
通过上图可以发现,类图主要由两部分组成,ObjectId/ObjectIdFactory,在类ObjectId中,主要实现了生产,解包,计算,转换,公开数据结构等操作,而ObjectIdFactory只有一个功能,就是生产Oid。
所以,我们知道,类ObjectId中的NewId实际是调用了ObjectIdFactory的NewId方法。
为了生产效率的问题,在ObjectId中声明了静态的ObjectIdFactory对象,有一些初始化的工作需要在程序启动的时候在ObjectIdFactory的构造函数内部完成,比如获取机器名称和进程编的号,这些都是一次性的工作。
<强>类ObjectIdFactory的代码实现强>
public class ObjectIdFactory { private 才能int 增量; private 才能;readonly  byte [], pidHex; private 才能;readonly  byte [], machineHash; private 才能readonly UTF8Encoding  utf8 =, new UTF8Encoding(假); private 才能readonly DateTime  unixEpoch =, new DateTime (1970,, 1,, 1,, 0, 0, 0,, DateTimeKind.Utc); public 才能;ObjectIdFactory () {才能 ,,,MD5 MD5 =, MD5.Create (); ,,,machineHash =, md5.ComputeHash (utf8.GetBytes (Dns.GetHostName ())); ,,,pidHex =, BitConverter.GetBytes (Process.GetCurrentProcess () .Id); ,,,Array.Reverse (pidHex); ,,}///才能,& lt; summary>///才能,产生一个新的,24,位唯一编的号///才能,& lt;/summary>///才能,& lt; returns> & lt;/returns> public 才能;ObjectId  NewId () {才能 ,,,int copyIdx =, 0; ,,,byte [], hex =, new 字节[12]; ,,,byte [], time =, BitConverter.GetBytes (GetTimestamp ()); ,,,Array.Reverse(时间); ,,,Array.Copy(时间,,0,,十六进制,,copyIdx,, 4); ,,,copyIdx +=, 4; ,,,Array.Copy (machineHash, 0,十六进制,,copyIdx,, 3); ,,,copyIdx +=, 3; ,,,Array.Copy (pidHex,, 2,,十六进制,,copyIdx,, 2); ,,,copyIdx +=, 2; ,,,byte [], inc =, BitConverter.GetBytes (GetIncrement ()); ,,,Array.Reverse(公司); ,,,Array.Copy(公司,,1,,十六进制,,copyIdx,, 3); ,,,return new ObjectId(十六进制); ,,} private 才能;int  GetIncrement(),=祝辞,System.Threading.Interlocked.Increment (ref 增加); private 才能;int  GetTimestamp(),=祝辞,Convert.ToInt32 (Math.Floor ((DateTime.UtcNow 作用;unixEpoch) .TotalSeconds)); }net核心中如何反解ObjectId