我一直在阅读有关事件采购模式的内容,如果您想重建系统,这可能非常有用。但是,如果我需要在处理新传入请求时运行事件重建,该怎么办?该场景是否有任何特定模式或最佳实践? 因此,如何确保新的传入请求在重放时不会搞砸我的系统,而不是安排系统停机时间,因为事件同步和序列对我的系统非常重要。它涉及更新依赖于事件序列的DB记录。有什么想法吗?
答案 0 :(得分:1)
我在类似情况下使用了CQRS + ES。 我使用准备好的数据创建了投影,我只能更新,但不能重建。 在每个查询中,我都会快速建立结果信息。
如果你需要执行一些长操作(比如db中的update),请使用sagas。生成事件 - >传奇 - >在saga结束并生成event2之后更新投影。
当然,事件收入和预测更新之间会有一些延迟。
了解更多关于你的系统以及这种变体对你来说是否足够好非常有趣。
答案 1 :(得分:1)
注意:在本示例中,所有ID都是6个随机字母数字,例如,它们可能是UUID或sha1。
如果您有以下事件:
WriteIndex | EventId | Type | streamId | Data
-------------------------------------------------------------------------------
1 | qcwbf2 | car.created | hrxs21 | { by: Alice, color: blue }
2 | e1owui | car.repainted | hrxs21 | { color: red }
3 | fjr4io | car.created | tye24p | { by: Alice, color: blue }
4 | fhreui | customer.created | b2dhuw | { name: Bob }
5 | urioe7 | car.sold | hrxs21 | { to: b2dhuw }
6 | fhreui | customer.renamed | b2dhuw | { name: Charlie }
-------------------------------------------------------------------------------
在您的预测中(6点之后):
CarId | Creator | Color | Sold | Customer | CustomerId
-------------------------------------------------------
hrxs21 | Alice | red | yes | Bob | b2dhuw
tye24p | Alice | blue | no | |
-------------------------------------------------------
CustomerId | Name
---------------------
b2dhuw | Charlie
---------------------
请注意,您的汽车投影错误,因为您没有正确地在汽车投影仪中收听“ customer.rename”。
您重写了所有投影机,并想重播。
您重播事件并转到此:
CarId | Creator | Color | Sold | Customer | CustomerId
-------------------------------------------------------
hrxs21 | Alice | red | yes | Charlie | b2dhuw
tye24p | Alice | blue | no | |
-------------------------------------------------------
但与此同时,在“重建汽车缓存”(投影不过是缓存)之外,有两个新事件出现:
WriteIndex | EventId | Type | streamId | Data
-------------------------------------------------------------------------------
7 | je3i32 | car.repainted | hrxs21 | { color: orange }
8 | 8c227x | customer.created | wuionx | { name: Dan }
9 | e39jc2 | car.sold | tye24p | { to: wuionx }
所以它“似乎”认为新的重建的新鲜缓存永远不会“恢复到当前状态”,因为现在查理(前鲍勃)的汽车现在是橙色而不是红色,已经创建了新客户,并且汽车号wuionx是现在归Dan所有。
原因:重建数千个事件可能需要一些时间。但是,仅重建几十个就可以快速点亮。
所以...让您的“重播器”改为具有这些表:(我假设WriteIndex对于启发是可靠的,但实际上,我可能会使用writeIndex以外的其他东西,这仅是出于说明目的) :
CarId | Creator | Color | Sold | Customer | CustomerId | LatestChangedBy
--------------------------------------------------------|----------------
hrxs21 | Alice | red | yes | Charlie | b2dhuw | 6
tye24p | Alice | blue | no | | | 3
-------------------------------------------------------------------------
因此,当要“消费”汽车tye24p时,您会看到它的最新更新是由于3而完成的,因此您只能在此聚合上“重播” 4端监听,因此您将得到以下结果:
CarId | Creator | Color | Sold | Customer | CustomerId | LatestChangedBy
--------------------------------------------------------|----------------
hrxs21 | Alice | red | yes | Charlie | b2dhuw | 6
tye24p | Alice | blue | yes | Dan | wuionx | 9
-------------------------------------------------------------------------
这是无效的,因为您已经在重播4至6时再次“重播”。
拥有一个全局重播计数器
CarId | Creator | Color | Sold | Customer | CustomerId
-------------------------------------------------------
hrxs21 | Alice | red | yes | Charlie | b2dhuw
tye24p | Alice | blue | no | |
-------------------------------------------------------
ReplayerMetaData
-------------------------------------------------------
lastReplayed: 6
-------------------------------------------------------
当您要访问任何内容时,请对“有待重播的任何新事件”进行SYNC“快速更新”。
如果您要访问car tye24p,您只会看到直到“索引9”的事件,然后重放了多达6的事件。然后,在“读取之前”强制“更新所有未决”并仅重放7、8和9.您最终得到了这个汽车缓存表:
CarId | Creator | Color | Sold | Customer | CustomerId
--------------------------------------------------------
hrxs21 | Alice | orange | yes | Charlie | b2dhuw
tye24p | Alice | blue | yes | Dan | wuionx
-------------------------------------------------------
ReplayerMetaData
-------------------------------------------------------
lastReplayed: 9
-------------------------------------------------------
使用此解决方案,您:
希望有帮助!
答案 2 :(得分:0)
根据您所描述的限制,听起来像 live 从零重建不能成为您计划的一部分。您可以改为进行A / B设置,在当时处于脱机状态的新系统上播放事件,然后在新系统赶上后切换到新系统。关键是旧系统和新系统都可以同时收听事件流。
如果您订阅了各种事件子集的系统,则可能只需要为其中一个子系统重播事件,并且仍然可以在没有该子系统的情况下满足您的同步/序列需求。
您可以通过在数据中包含事件序列号并使序列相关服务延迟处理(如果尚未看到该事件)来阻止对过时信息采取行动。
答案 3 :(得分:0)
要将事件投影到读取模型,您需要使用某种追赶订阅,例如EventStore提供的订阅。在这种情况下,您的新活动将保存到商店,但不会立即投影。
但是,您必须意识到您的用户将开始查看严重过时的数据并根据不一致的读取模型执行操作。我宁愿避免这种情况,让系统重建。
我同意第一个答案,你可能想要同时建立一个新的阅读模型,更新旧的并在某个时候进行切换,甚至可能不是所有用户都是。