我想知道当每个聚合获得自己的事件流时,如何将SQL数据库设计为事件存储:
每个Stopwatch stopwatch = Stopwatch.StartNew();
HashSet<FieldInfo> fieldInfos = new HashSet<FieldInfo>();
//Loop over every single bit combination
for (int i = 0; i < 0x01111111; i++)
{
BindingFlags f = (BindingFlags) i;
FieldInfo[] infos = thread.GetType().GetFields(f);
foreach (FieldInfo info in infos) fieldInfos.Add(info);
}
Debug.Log($"Time to search: {stopwatch.Elapsed.TotalMilliseconds:n0}ms");
stopwatch.Restart();
Debug.Log(fieldInfos.Count);
foreach (FieldInfo info in fieldInfos)
{
Debug.Log(info.Name);
Thread.Sleep(10);
}
Debug.Log($"Time to log: {stopwatch.Elapsed.TotalMilliseconds:n0}ms");
代表一个事件
X
我会为每个用户流创建一个单独的表吗?
还是我以某种方式管理一个表中的所有用户?
要求:
P.S。如果有人为我的要求提供一些示例查询,那将是很好的
答案 0 :(得分:2)
我知道,大多数SQL支持的事件存储示例都使用单个事件表来存储数据库中的所有聚合。基本形状是用于保存事件的BLOB列,然后是用于有用的元数据的其他列。
eventide-project是一个很好的参考,该项目具有一个开放源代码模块,用于在Postgresql:message-store-postgres-database之上构建消息存储。 messages table非常简单:将jsonb列分别用于数据和元数据,然后添加其他列以支持对常见用例进行有效查询。
Gabriel Schenker在Los Techies撰写了一系列文章:How We Got Rid of the Database。
Konrad Garus写道:Achieving Consistency in CQRS with a Linear Event Store。
按时间顺序保留事件
对于单个流,通常通过为流中的每个事件写一个本地序列号来维持顺序。您需要做一些工作,以确保在对同一流执行并发写入时,先写者获胜。流中的每个事件与所有具有较低本地序列号的事件都具有happens-after
关系。
在多个流中,不一定严格定义“顺序”。不能保证通过不可靠的网络发送的消息将按其发送顺序到达。 Eventide使用global_position
列来跟踪将事物写入数据库的顺序。
在事件上添加时间戳可以使您对时间进行某种程度的测量,但是,当然,如果使用不同的时钟来测量时间,则不能保证排序的有效性。
很少删除事件
从事件表中删除行可能会使您不高兴。考虑将行标记为已删除或覆盖事件数据,而不要在记录中引入空白。
事件源的通常纪律是通过添加适当的补偿事件来修复业务错误,而不是尝试更改历史记录。
您需要根据法律(GDPR)删除数据
社区中对此进行了大量讨论。真正的答案是,您需要使数据隐私成为设计中的头等大事。用不包含敏感信息的副本替换事件是一种可能的方法,将敏感信息存储在事件历史记录之外(在专用机密管理器中)是另一种可能性。
注意:以上内容不应被视为适用于任何司法管辖区的法律建议。