是否有托管系统级序列号生成器?DateTime.Now.Ticks 不会这样做,因为我正在执行的操作有时每个时钟周期都会发生多次。


要求说明:

  • 与进程无关——实际上只有一个进程可以访问它。
  • 性能至关重要!这用于记录广告服务器上的展示次数,可以达到 1k/秒

它需要是以下之一:

  • 每个刻度都会重置的 4 字节序列号
  • 12 字节序列号 - 实质上为 DateTime 添加 4 字节粒度
有帮助吗?

解决方案

无意为此,但是您可以使用 system.diagnostics.performancecounter. 。您也可以使用注册表,但是您需要序列化读取/写入访问的过程。

System.Diagnostics.PerformanceCounter pc 
    = new System.Diagnostics.PerformanceCounter("SeqCounter", "SeqInstance");
long myVal=pc.Increment();

编辑

我对此的想法越多,我认为这可能是一个不错的解决方案。增量将通过原子操作增加计数器1,该操作应在系统上累积所有过程。

编辑

根据您的编辑,我不建议使用性能计数器。性能计数器是一种缠绕多个过程的方法。我不确定如何编码内部实现。

您为什么不能只使用静态变量并将其递增?如果您希望这是线程安全,您将不得不锁定某些东西。

system.threading.interlocked.increment

仅供参考:如果您在32位系统上使用长版本,则不会安全。


编辑以显示我使用的实现(DS):

public static class Int32Sequencer
{
    private static Int32 lastSequence = Int32.MinValue;
    private static Object lockObject = new Object();
    public static Int32 GetNextSequence()
    {
        lock (lockObject)
        {
            unchecked { lastSequence++; }
            return lastSequence;
        }
    }
}

其他提示

GUID和您要获得的一样接近,但是这些GUID是“独特的”,不一定是顺序的。如果您真的希望在系统级别的多个过程中进行顺序,则可能必须自己滚动。

编辑:

好的,因此,根据您的新要求,我将假设:

  1. 只有一个过程需要完成工作
  2. 您正在附加到数据库

所以这是我建议的:

  1. 在此过程启动时,请查询DB的最后(最大)值(如果不存在,则为0)。
  2. 为每个DB行使用简单的长而增量。由于您的数据率很高,您将要分批插入。

那应该做到。把事情简单化。这没有锁,在启动时有轻微的(可以忽略的)命中,并且在您的DB中的顺序数字。只要您只有一个流程运行它,则该算法也是过程进行的。

我认为最接近的是一个GUID,我敢肯定,您最多只能部分顺序。

这里有一篇文章为SQL Server提供了一些详细信息:SQL Server中的顺序GUID 由于GUID的随机性,该技术用于最大程度地减少页面拆分。也许此链接会给您一些提示或想法。

我认为我们需要更多地了解您想要的内容。您能稍微澄清一下您的问题吗?特别是服务...

  • 是否需要在所有过程,一个过程或特定用户中工作?
  • 数字必须是唯一的还是仅是顺序的?

基于您的问题,您可能正在寻找几个不同的项目。

在系统上的所有过程中需要一个顺序的数字组

AFAIK,没有这样的服务。一个人应该很容易编写,但是让它在所有过程中工作都是棘手的。

在系统上的所有过程中需要一个唯一的顺序数字组

第一个问题的略有变化。这样的服务不存在,因为它是不可能实施的。没有办法使用内置数据类型保证唯一的顺序数字,仅仅是因为该值最终会溢出并为您提供重复的数字。

需要一种在系统中获得唯一值的方法

正如其他几个用户提到的那样,最佳选择是系统。您可以使用Guid.NewGuid()创建一个新的。为了几乎所有目的,它们都可以被认为是独特的,但不是顺序的。

我只为了安全性,我喜欢数据库选项。确保在服务器之间安装带有带宽的Monster SQL Server,但具有足够的内存。与此类似的系统是在我有史以来工作的第一家公司(甚至在我成为程序员之前)实现的,而且非常狡猾。您可能会为扩展这一点而战。

另一个选项是将单例函数实现到您的代码中...提供只有一个应用程序域将调用它。可能比进行数据库旅行快一点。但是,如果您要将这些内容记录到数据库中。...组合两者...运行singleton以换取速度,然后在资源允许时写入数据库。

同样,如果顺序要求不那么强大,则GUID将是您最好的选择。

没有锁定就无法获得单个连续序列。无论您使用什么机制来分配下一个值(性能计数器、静态变量等),当两个线程同时需要下一个值时,一个线程必须等待另一个线程。

我要做的第一件事是编写一个测试程序,生成大量线程,每个线程重复调用一个锁定增量函数,例如 Daniel Schaffer 发布的函数。这将让你找到你的应用程序开始崩溃的阈值——它花费更多时间等待的阈值 Monitor.Enter 比做任何其他事情。

如果这最终成为一个问题 - 我敢打赌,如果您正在谈论的卷是真实的,那么您应该让每个线程维护自己的顺序计数器,您可以通过标记计数器字段来做到这一点与 ThreadStaticAttribute. 。然后,您可以根据线程 ID 和计数器的组合生成唯一标识符。

如果您不使用线程池,这种方法将不起作用(因为当它所属的线程死亡时,计数器就会死亡)。您可能还希望使应用程序的启动计数成为复合 ID 的一部分,这样您就不必将线程计数器写入持久存储。(如果您不这样做,当您重新启动服务器时,线程将再次开始生成为零的计数器,并且如果您的应用程序创建了一个与早期实例具有相同 ID 的线程,您将获得重复的标识符。)

这显然编写起来(或者更重要的是测试)并不简单,所以我绝对建议首先证明它是必要的。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top