net核心中如何反解ObjectId

  介绍

这篇文章主要讲解了。”网络核心中如何反解ObjectId”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习”。网络核心中如何反解ObjectId”吧!

<强>前言

在设计数据库的时候,我们通常需要给业务数据表分配主键,很多时候,为了省的事,我都是直接使用GUID/UUID的方式,但是在MonggoDB中,其内部实现了ObjectId(以下统称为Oid)。并且在。NETCore的驱动中给出了源代码的实现。

经过仔细研读官方的源码后发现,其实现原理非常的简单易学,在最新的版本中,阉割了解压函数,可能是官方觉得解包是没什么太多的使用场景的,但是我们认为,对于数据溯源来说,解包的操作实在是非常有必要,特别是在目前的微服务大流行的背景下。

为此,在参考官方代码的基础上进行了部分改进,增加了一下自己的需求。本示例代码增加了解包的操作,对字符串的隐式转换,提供读取解包后数据的公开属性。

<强> ObjectId的数据结构

首先,我们来看Oid的数据结构的设计。

。网络核心中如何反解ObjectId

从上图可以看出,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

通过上图可以发现,类图主要由两部分组成,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