如何在事件采购环境中处理非常大的预测?

时间:2018-03-15 09:52:36

标签: event-sourcing

我想探讨事件采购对vs的影响。主动记录。

假设我有有效负载的事件,如下所示:

{
  "type": "userCreated", 
  "id": "4a4cf26c-76ec-4a5a-b839-10cadd206eac", 
  "name": "Alice", 
  "passwordHash": "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
}

......和......

{
  "type": "userDeactivated", 
  "id": "39fd0e9a-1025-42e6-8793-ed5bfa236f40"
}

我可以使用这样的reducer来达到我系统的当前状态:

const activeUsers = new Map();

for (const event of events) {

  // userCreated
  if (event.payload.type == 'userCreated') {
    const { id, name, passwordHash } = event.payload;
    if (!activeUsers.has(id)) {
      activeUsers.set(id, { name, passwordHash });
    }
  }

  // userDeactivated
  if (event.payload.type == 'userDeactivated') {
    const { id } = event.payload;
    if (activeUsers.has(id)) {
      activeUsers.delete(id);
    }
  }
}

但是,我无法将整个用户表放在一个Map中。

所以我觉得每个用户都需要一个reducer:

const userReducer = id => // filter events by user id... 

但这会导致性能下降,因为我需要为每个新用户的所有事件运行reducer。

我还可以通过他们的id函数分享用户:

const shard = nShards => id => {
  let hash = 0, i, chr;
  if (this.length === 0) {
    return hash;
  }
  for (i = 0; i < this.length; i++) {
    chr   = this.charCodeAt(i);
    hash  = ((hash << 5) - hash) + chr;
    hash |= 0; // Convert to 32bit integer
  }
  return hash % nShards;
};

然后地图将不那么庞大。

在事件采购模型中,这个问题通常是如何解决的?

1 个答案:

答案 0 :(得分:0)

据我了解,您认为您需要使用reducer重播所有事件才能查询所有用户,对吗?

这是cqrs与read models/denormalizers一起发挥作用的地方。

几乎每个人都在做的事情是拥有读取模型(例如,存储在sql数据库中或其他擅长查询数据的模型)。创建新事件时,该读取模型将不断更新。

当需要查询所有用户时,可以查询此读取模型,而不重播所有事件。