卡夫卡验证有状态处理消息

问题描述:

我有一个应用程序,其中多个用户可以发送REST操作来修改共享对象的状态。 修改对象时,会发生多个操作(数据库,审计,日志记录...)。卡夫卡验证有状态处理消息

并非所有操作都是有效的,例如,您不能在删除对象后修改它。

使用卡夫卡我在想下面的架构:

  1. 休息操作排队卡夫卡话题。
  2. 对同一对象的操作将进入同一分区。因此,所有的对象的操作将在序列和由消费者
  3. 消费者听分区处理,使用内存数据库
  4. 确认操作如果操作是有效的,那么被发送到一个“有效操作主题” otherways被发送到‘无效操作主题’
  5. 其他消费者(DB,日志,审计)正在收听的‘有效操作主题’

我不是很肯定点3号。 我不喜欢保持所有对象状态的想法。 (我有数十亿的对象,即使一个对象可以是10MB的大小,我需要存储以验证其状态只有几K字节...

但是,这是一种常见模式吗?否则,你如何验证某些操作的有效性?

另外你会用什么作为内存数据库?它必须是高度可用的,容错和支持事务(读写)。

+0

我正在考虑使用此:https://samza.apache.org/learn/documentation/0.7.0/container/state-management.html ... –

我相信这是一个非常有效的模式,实质上是对事件源CQRS模式的变体。

例如,Lagom implements their CQRS persistence in a very similar fashion(虽然基于完全不同的工具集)

的几点:

  • 你是正确的关于需要序贯操作:因为所有的状态突变,需要根据前一次突变的结果,在执行过程中必须有强大的顺序。对于这种情况通常是这种情况,所以我们希望能够尽可能水平地扩展这些操作,使得每个序列操作都与其他许多序列并行发生。在你的情况下,我们有一个这样的序列每个共享对象。
  • 依靠Kafka按键进行分区是实现该目的的一种好方法(假设您未将max.in.flight.requests.per.connection设置为高于默认值1)。在这里,Lagom也有一个类似的方法,让它们的持久实体分布并且是单线程的。我不是说Lagom更好,我只是安慰你,其实这是被其他人使用的方法:)

  • 你的模式的一个关键方面是将命令转换为事件:行话命令被视为影响国家的请求,并可能由于各种原因被拒绝。事件是对过去发生的状态更新的描述,并且从接收它的人的角度来看是无可辩驳的:事件总是说实话。你描述的过程将是一个处于两者边界的控制器:它负责将命令转换为事件。

  • 从这个意义上讲,您提到的“有效操作主题”将是您的过程的状态更新的事件源描述。因为它全部由卡夫卡支持,所以它可以任意分割,因此可以扩展,这真是太棒了:)
  • 不要担心所有对象的大小,它必须以某种方式坐在某个地方。既然你有这个控制器把命令转换成事件,这个控制器成为与该对象有关的主要真相源,并且这个控制器负责存储它:这个控制器处理你的事件的主存储器,所以你必须将空间它。你可以使用Kafka Streams's Key value store:那些对你的每个处理实例都是本地的,但是如果你使它们持久化,它们在处理可用RAM的数据方面没有问题。由于RocksDB,现场数据泄漏到磁盘上,甚至更多的幕后故事都来自于事件源,因此您的州商店被复制,并且如果需要将在另一台机器上透明地重新创建

我希望这可以帮助您最终确定您的设计:)