2013-07-05 2 views
3

Итак, вот в чем проблема. Мы используем CQRS с Event Sourcing, и мы используем поток событий для каждой последовательности экземпляра агрегатного экземпляра. И каждый поток сохраняется с соответствующей датой создания, но дело в том, что все это происходит слишком быстро, а это означает, что некоторые из совокупных потоков событий, которые являются частью некоторого процесса (регистрации, уведомления и т. Д.), Выходят с той же самой датой. Поэтому, когда нам приходится переигрывать события, упорядочение потоков по дате создания не работает beacouse, есть потоки событий, которые зависят от времени, но они происходят так быстро, что похоже, что они были параллельными (это означает, что мы использовали DateTime.UtcNow и даты равны наносекунде).Что делать, если DateTime.Now не достаточно хорош?

Для тех, кто не знает, что CQRS или Event Sourcing является

Представьте себе, что у вас есть список ресурсов, и каждый элемент имеет свою дату создания. И его crutial, чтобы знать порядок создания предметов в Списке. Имейте в виду, что существует несколько потоков, создающих и добавляющих элементы в список. Проблема в том, что когда поток должен создавать и добавлять в список два элемента, даты их создания совпадают, и вы не можете упорядочить их по дате правильно. Btw pc имеет значение на моем компьютере DateTime.Now не равен DateTime.Now на сервере это. Фактически на коллеги pcadding 25000 раз DateTime.Now к списку приводит к тому, что первый и последний элементы списка равны наносекунде (точное совпадение)

+0

Связанные: ['Что не так с DateTime в любом случае?'] (Http://noda-time.blogspot.com/2011/08/what-wrong-with-datetime-anyway.html) –

+1

Почему использовать инкрементный идентификатор вместе со временем создания? – Anri

+0

Сложный: DI пытается сделать это атм, но он борется –

ответ

2

временная метка является полезный фрагмент метаданных. Это не так, как вы обнаружили, - надежный критерий упорядочения. Представьте, что вы придумали какое-то решение на своей машине, но теперь вам нужно использовать две машины? Можете ли вы синхронизировать часы в течение наносекунды? Меньше?

В случае поиска источников, типичной гарантией является то, что события сортируются в пределах одного потока, например. один агрегат. В любом случае, это ваша гарантия транзакции. Почему бы просто не использовать целое число для отслеживания последовательности каждого события в потоке? Ваш агрегат может сгенерировать его, поскольку он все равно отслеживает все события.

Если вы хотите упорядочить по потокам, вам придется либо сгенерировать этот порядковый номер по центру (с помощью сочетания, который представляет), либо принять, что множественные чтения из нескольких потоков не всегда возвращают события в том же порядке, события в пределах одного потока должны быть отсортированы.

1

Вы можете получить точный номер, который вы можете использовать как временную метку вызвав Windows API QueryPerformanceCounter(), который должен, дает вам согласованное значение между потоками с очень высоким разрешением.

Конечно, это дает только значения, относящиеся к одному конкретному компьютеру; его нельзя использовать, если вы хотите сравнить временные метки, созданные на двух разных компьютерах.

Однако, обратите внимание, это (из документации API Windows):

На многопроцессорных компьютерах, это не имеет значения, какой процессор называется. Тем не менее, вы можете получить разные результаты на разных процессорах из-за ошибок в базовой системе ввода/вывода (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);