4

好的,这就是问题所在。我们将 CQRS 与 Event Sourcing 结合使用,并且我们在每个聚合实例的提交序列中使用事件流。并且每个流都保留其各自的创建日期,但问题是所有这些都发生得太快了,这意味着作为某些过程(注册、通知等)的一部分的一些聚合事件流出来了与完全相同的日期。因此,当我们必须重播事件时,按创建日期对流进行排序不起作用,因为有些事件流在时间上是相关的,但它们发生得如此之快以至于看起来它们是并行发生的(这意味着我们使用 DateTime.UtcNow 和日期等于纳秒)。

对于那些不知道 CQRS 或事件溯源是什么的人

假设您有一个资源列表,并且每个项目都有其创建日期。了解列表中项目的创建顺序至关重要。请记住,有多个线程在列表中创建和添加项目。问题是当一个线程必须在列表中创建和添加两个项目时,它们的创建日期匹配你不能正确地按日期排序。顺便说一句,我的电脑上的电脑很重要 DateTime.Now 不等于服务器上的 DateTime.Now 。实际上,在同事将 25000 次 DateTime.Now 加入到列表中时,列表的第一个和最后一个元素等于纳秒(精确匹配)

4

2 回答 2

3

时间戳是一种有用的元数据。正如您所发现的那样,这不是一个可靠的排序标准。想象一下,您在您的机器上想出了一些解决方案,但现在必须使用两台机器?你能在一纳秒内保持他们的时钟同步吗?较少的?

在事件溯源中,典型的保证只是事件在单个流中排序,例如一个聚合。无论如何,这是您的交易保证。为什么不只使用整数来跟踪流中每个事件的序列?您的聚合可以生成它,因为它一直在跟踪所有事件。

如果您想跨流排序,则必须集中生成该序列号(使用表示的耦合),或者接受多个流的多次读取不会总是返回相同顺序中的事件,只是一个流中的事件应该排序。

于 2013-07-11T12:44:52.540 回答
1

您可以通过调用 Windows API 获得一个准确的数字,该数字可以用作时间戳,QueryPerformanceCounter()应该为您提供具有非常高分辨率的线程之间的一致值。

当然,这只会为您提供与一台特定计算机相关的值;如果要比较在两台不同计算机上创建的时间戳,则不能使用它。

但是,请注意这一点(来自 Windows API 文档):

在多处理器计算机上,调用哪个处理器并不重要。但是,由于基本输入/输出系统 (BIOS) 或硬件抽象层 (HAL) 中的错误,您可能会在不同的处理器上获得不同的结果。

(我自己没有在任何硬件上遇到上述错误。)

您可以通过 C# 获取性能计数器,如下所示:

public long PerformanceCounter()
{
    long result;
    QueryPerformanceCounter(out result);
    return result;
}

[DllImport("kernel32.dll", SetLastError=true)]
static extern bool QueryPerformanceCounter(out long lpPerformanceCount);
于 2013-07-05T08:06:06.020 回答