我想尝试在事件采购应用程序中使用Cassandra作为事件存储。我对事件存储的要求非常简单。事件“架构”将是这样的:
我对卡珊德拉来说是全新的,所以请原谅我对我即将写的东西的无知。我只想在这些数据上运行两个查询。
我的想法是在CQL中创建一个Cassandra表,如下所示:
CREATE TABLE events (
id uuid,
seq_num int,
data text,
timestamp timestamp,
PRIMARY KEY (id, seq_num) );
这似乎是一种模拟问题的明智方法吗?而且,重要的是,使用复合主键是否允许我有效地执行我指定的查询?请记住,在给定用例的情况下,对于相同的聚合根id,可能会有大量事件(具有不同的seq_num)。
我特别关注的是第二个查询在某种程度上效率低下(我在这里考虑二级索引......)
答案 0 :(得分:6)
您的设计似乎很好地用“cassandra术语”建模。 “复合键”表确实支持您需要的查询,您可以使用以下内容:
select * from events where id = 'id_event'
; select * from events where id = 'id_event' and seq_num > NUMBER
; 我认为第二个查询效率不高,但它可能会返回很多元素......如果是这种情况,您可以设置要返回的事件的“限制”。如果可以,您可以使用limit
关键字。
使用复合键似乎非常适合您的特定要求。使用“二级索引”似乎没有带来太大的影响......除非我错过了你的设计/要求。
HTH。
答案 1 :(得分:2)
您所获得的是好的,除非特定聚合的许多事件发生。你可以做的一件事是创建一个静态列来保持" next"和" max_sequence"。这个想法是静态列将保存此分区的当前最大序列,以及"仿真id"为下一个分区。然后,您可以为每个分区存储100或1000个事件。您基本上已经完成的工作是将聚合事件分成多个分区。这将意味着查询和存储的额外开销,但同时防止无限增长。您甚至可以为聚合创建分区查找。真的取决于你的用例以及如何"聪明"你希望它成为。
答案 2 :(得分:2)
我一直在使用Cassandra进行非常类似的场景(每行100k +列),并以接近你的模型结束。我也同意emgsilva认为二级指数可能不会带来太多。
有三件事对我们的事件存储的良好性能有重要意义:使用复合列,确保列的排序顺序很好(Cassandra按行按行排序),并使用紧凑的存储如果可能的话。
请注意,紧凑型存储意味着您只能拥有一个值列。因此,您需要将所有其他列作为密钥的一部分。
对你而言,架构将是:
CREATE TABLE events (
id uuid,
seq_num int,
timestamp timestamp,
data text,
PRIMARY KEY (id, seq_num, timestamp))
WITH COMPACT STORAGE;
答案 3 :(得分:0)
您的分区键太精细,您应该创建复合分区键或更改它以获得更好的时间序列建模性能。例如
CREATE TABLE events (
event_date int,
id timeuuid,
seq_num int,
data text,
PRIMARY KEY (event_date, id) );
这样,您的ID将成为一个聚类列,只是为了保证事件的单一性,您的分区键(即20160922)可以每天对所有事件进行分组。您也可以将其更改为月份。避免使用uuid使用timeuuid,它已经存储了时间戳信息。
答案 4 :(得分:0)
该设计似乎与Cassandra如何存储数据(主键的第一部分)保持一致,即您的“ id”将用于在单独的节点/ v节点上划分数据(取决于集群的方式)配置),对于Cassandra来说,这将使您为第一个查询获取数据非常容易,因为它仅需触摸单个分区,现在根据键的第二部分将是一个聚簇键,即将指定数据的方式在该分区内排序,这是您的第二个查询的全部内容。请记住,只要所有数据的设计方式都使得表上的每个查询仅涉及单个分区,那么您就可以开始使用。同样,如果您担心第二个查询将返回大量数据,则始终可以选择Cassandra固有地为范围查询提供的分页。
答案 5 :(得分:-4)
我不赞成你的设计在eventstore上保存aggregateroot.you可以保存domainevent的灵活性。 我解释eventdomain是最细粒度的数据,使得应用程序状态的变化.aggregateroot不与eventstore不匹配,它用于数据交换或boundedcontext。 当您使用域事件时,您可以使用plolygot建模重建您的数据甚至aggregateateroot。您可以管理模型以满足您的客户和约束的需要。所以您为domainobject之间的链接建模图形,之后使用neo4j,此外您还建模聚合模型和你使用documentdatabase。我的意思是你有机会改变模型并使用方便的持久性引擎。这是polygot数据和polygot持久性之间的区别。 在你的策略中,我理解两种方式: 如果您需要在domainevent和cassandra数据库上建模的事件。 如果您需要聚合数据或模型而没有事件源,则使用文档化数据库,您可以检索这两个查询。
你可以消除对域驱动设计的困惑。