gpt4 book ai didi

cqrs - 事件溯源 - 事件重放

转载 作者:行者123 更新时间:2023-12-01 00:36:27 26 4
gpt4 key购买 nike

我一直在阅读有关事件溯源模式的信息,如果您想重建系统,它会非常有用。

但是,如果我需要在为新的传入请求提供服务时运行事件重建怎么办?该场景是否有任何特定模式或最佳实践?

因此,与其安排系统停机时间,我如何确保新传入的请求不会在我的系统重放时搞砸,因为事件同步和顺序对我的系统非常重要。它涉及更新依赖于事件序列的数据库记录。

有什么想法吗?

最佳答案

注意:对于此示例,所有 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.renamed”收听到汽车投影仪中。

你重写了所有的投影仪并想要重播。

你的恐惧

你重播事件并得到这个:
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 现在由担。

您的解决方案
  • 使用“索引”(注意,需要仔细设计)或“时间戳”(注意将纠正事件注入(inject)过去日期!
  • 在读取缓存时“确保”您“应用”待应用到同步模式(不是异步)的“最新更改”。

  • 原因:重建数千个事件可能需要时间。但是重建几十个应该很快。

    Quick-n-Dirty 解决方案

    所以......让你的“replayer”改为拥有这些表:(我假设 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
    -------------------------------------------------------

    当您想访问任何内容时,您可以对“任何待重播的新事件”进行同步“快速更新”。

    如果您想访问 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
    -------------------------------------------------------

    总体

    使用此解决方案,您:
  • 可以在切换读取模型之前进行无限次数的试验。
  • 在您进行所有试验时可以保持“在线”。
  • 当您的系统“准备好”进行最终重建时(想象一下处理 100 万个事件需要 1 小时),您只需在系统在线的情况下运行它。
  • 大型重建后,说你的 lastReplayed = 1.000.000。如果在那一小时内,出现了 2.000 个新事件,您就可以再次“重播那些最新事件”。
  • 想象那些 2.000 需要 5 分钟,您的指针现在是 1.002.000。想象一下,在那 5 分钟内,又有 300 个事件发生:
  • 重播“仅那些最新的”,您的指针将是:1.002.300
  • 一旦您“几乎 catch ”(无论是否还有 50 个事件的差距),您只需将读取模型(仅通过配置标志)切换到新模型 => 这意味着您 不得进行完整部署,您必须已经部署了能够从此处或从那里读取的版本,因此切换是“立即的”。
  • 切换后,您只需在阅读中“确保”您“强制同步应用最新内容”。
  • 这只会影响第一次读取,最多应该是 1 或 2 秒......下一次读取很可能已经同步,所以继续检查差距没有任何性能损失,它会说“你需要更新 0 个事件”并完成。

  • 希望有所帮助!

    关于cqrs - 事件溯源 - 事件重放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40742568/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com