如何为聚合计数进行Cassandra数据建模



假设我的服务中有客户订单数据,我想对这些数据进行一些报告。所有客户订单都保存在Cassandra表中,这样我就可以获得给定客户的所有订单:

TABLE customer_orders
store_id uuid,
customer_id text,
order_id text,
order_amount int,
order_date timestamp,
PRIMARY: KEY (store_id, customer_id)

但我也想找到所有有一定数量订单的客户。理想情况下,我希望在Cassandra中的一个现成的查询表中有这个。例如"获取所有有1个订单的客户"。

因此,我有一张这样的表格:

TABLE order_count_to_customer
store_id uuid,
order_count int,
customer_id text
PRIMARY KEY ((store_id, order_count), customer_id)

因此,我们的想法是,当订单到达时,这两个表都将被更新。

所以我创建了第三个表:

TABLE customer_to_orders_count
store_id uuid,
customer_id text,
orders_count counter,
PRIMARY KEY (store_id, orders_count)

订单到达时:

  1. 我把它保存在的第一张表中

  2. 然后通过将第三个表中的计数器递增1来更新该计数器。

  3. 然后我读了第三张表中的计数器,并在第二张表中插入了一条新记录。

当我需要查找具有给定订单数量的所有客户时,我只查询第二个表。

这样做的问题是计数器不是原子性的和一致的。如果我将计数器更新为3,则不能保证当我下一次读取它以更新第二个表时,它将是3。可能是2。即使我在更新计数器之前读取了计数器,它也可能是几步后的某个值。所以也不能保证。请注意,我知道Cassandra中计数器的局限性,我并不是在问如何解决计数器的问题。

我举这个例子是为了寻求一些关于如何对数据建模的一般建议,以便能够对其进行聚合计数。当然,我可以使用Spark直接对示例中的第一个表进行聚合查询。但在我看来,还有一些更聪明的方法可以做到这一点,Spark也会将整个表数据带入内存。

您是否想过使用CQL Batch命令。https://docs.datastax.com/en/cql/3.1/cql/cql_reference/batch_r.html

您可以将其与所有步骤一起使用,以将所有步骤保留在一个逻辑原子事务中,在该事务中,它们要么全部成功,要么全部失败。但是,此功能确实会影响性能。

相关内容

  • 没有找到相关文章

最新更新