concurrency - 事件溯源 : concurrently creating conflicting events

标签 concurrency apache-kafka event-sourcing

我正在尝试使用 Kafka 实现一个事件溯源系统,但遇到了以下问题。在新用户注册期间,我想检查用户提供的用户名是否已被使用。但是,请考虑 2 个用户尝试同时注册提供相同用户名的情况。

根据我对 ES 工作原理的理解,处理注册请求的 Controller 将检查请求是否有效,然后它会向 Kafka 发送一个新事件(例如 NewUser),最后该事件将被另一个事件接收 Controller 将它保存在一个物化 View 中(例如 Postgres DB)。问题是请求的验证是针对物化 View 完成的,但对它的实际持久化发生在稍后。因此,由于 2 个请求是并行处理的(由不同的服务实例),它们可能都通过了验证,从而导致 2 NewUser消息。但是,当第二个 Controller 尝试保留那些 2 NewUser 时由于违反了用户名的唯一性约束,保存第二个事件的数据库中的消息将失败。

关于如何解决这个问题的任何想法?

谢谢。

更新:

特别是,我想验证以下是否是解决问题的可接受方法:

  • 使用用户名作为用户 ID(限制性)
  • 将事件发送到按用户名和验证时分区的主题
    完成向另一个主题发送事件
  • 最佳答案

    During a new user sign-up I want to check if the username the user provided is already taken.



    您可能想在 Set Validation 上查看 Greg Young 的文章.

    In my understanding of how ES works the controller that processes the sign-up request will check if the request is valid, it will then send a new event (e.g. NewUser) to Kafka, and finally that event will be picked up by another controller which will persist it in a materialized view (e.g. Postgres DB).



    这与通常的安排略有不同。 (您可能还想查看 Greg 在 polyglot data 上的演讲。)

    假设我们从两个作家开始;这很好,但是如果有一个单一的事实点,那么您将需要在某处进行同步。

    通常的安排是使用一种乐观并发的形式;在处理请求时,您保留原始状态的副本,然后进行计算,最后将记录簿发送“replace(originalState,newState)”。

    所以在这一点上,我们有两篇文章正在奔向记录簿
    replace(red,green)
    replace(red,blue)
    

    在记录簿中,写入是按系列处理的。
    [...,replace(red,blue)...,replace(red,green)]
    

    所以当记录簿处理时replace(red,blue) ,它会检查是的,状态当前为红色,并以蓝色交换。稍后,当记录簿尝试处理 replace(red,green) 时,记录簿执行检查,由于状态不再是红色而失败。

    所以其中一个写入成功,另一个失败;后者可以向外传播失败,或重试,或者……这取决于所讨论的特定机制。当然,重试应该意味着重新加载“原始状态”,此时模型会发现之前的某些编辑已经声明了用户名。

    Any ideas on how to address this?



    每个流的单个编写器使剩下的问题变得非常简单,因为消除了模型的多个内存副本所带来的歧义。

    使用同步写入持久存储的多个写入器可能是最常见的设计。它需要一个事件存储来理解写入流中特定位置的想法——也就是“预期版本”。

    您可以执行异步写入,然后开始执行其他工作,直到收到写入成功的确认(或未成功,或直到超时,或)...

    没有魔法——如果你想要唯一性(或任何其他类型的不变强制,就此而言),那么每个人都需要就一个单一的权威达成一致,而其他任何想要提出改变的人都不知道它是否已经存在在没有得到权威的回复的情况下被接受,并且需要为被拒绝的提案做好准备。

    (注意:这应该不足为奇——如果您使用的是将当前状态存储在 RDBMS 中的传统设计,那么您的权限将是数据库中的用户表,对用户名列具有唯一性约束,并且比赛将在试图首先完成交易的两个插入语句之间进行....)

    关于concurrency - 事件溯源 : concurrently creating conflicting events,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43944813/

    相关文章:

    apache-spark - spark-submit 类路径问题与 --repositories --packages 选项

    sql-server - 如何使用 SQL Server 2008 R2 作为 ActiveMQ 5.9 的持久存储

    math - 如何使用 Welford 的在线算法计算更新和删除的值

    java在并发机制中设计任务

    apache-kafka - 远程找出Kafka版本

    java - Kafka Stream - 只有一个实例从分区读取

    cqrs - 什么是事件溯源中的 react 器/ react ?

    go - 选定组中的 channel 在指定时间内没有接收到信号时跳出循环

    java - 如何轮流监听两组线程获取synchronized section?

    mysql - 我想向客户销售固定数量的产品。 spring jpa如何管理并发?