因此,我正在设计这个数据模型来跟踪产品价格。
一个产品可以被多个用户关注,一个用户可以关注多个产品,因此这是一个多对多的关系。产品受到持续跟踪,但只有在与前一个价格不同的情况下,才会插入新的价格。
用户已经为他们关注的产品设置了价格上限,所以每次价格变化时,都会检查偏好,如果价格低于他们的价格,就会通知用户。
因此,最初我想到了以下产品模型:

然而,"subscriberEmails“是一个列表集合,可以处理多达65536个元素。但作为一个大数据解决方案,这是我们不想要的边界。因此,我们最终为此编写了一个单独的表:

因此,现在"usersByProduct“最多可以有20亿列,这很公平。用户偏好被存储在“地图”中,这也是有限的,但我们认为这是一个很好的最大数量的产品,以供用户遵循。
现在我们面临的问题是:
每次我们想要更新产品的价格时,我们都必须像这样进行查询:
INSERT INTO products("Id", date, price) VALUES (7dacedd2-c09b-46c5-8686-00c2a03c71dd, dateof(now()), 24.87); // Example only但是INSERT操作不接受除(如果不存在)以外的其他条件子句,这不是我们想要的。只有当价格与前一个不同时,我们才需要更新它,所以这迫使我们进行两个查询(一个用于读取当前值,另一个用于在必要时更新它)。
警局。UPDATE操作确实有IF条件,但这不是我们的情况,因为我们需要插入。
UPDATE products SET date = dateof(now()) WHERE "Id" = 7dacedd2-c09b-46c5-8686-00c2a03c71dd IF price != 20.3; // example only 发布于 2015-02-09 23:30:01
不要试图在cassandra数据库上应用普通模型。它可能会起作用,但你会得到糟糕的性能和可伸缩性。
Cassandra数据建模的推荐方法是首先找出对数据库的读查询,并组织数据,使这些读操作成本更低。您可能需要在某种程度上复制写入,但这是可以的,因为在Cassandra中写入非常便宜。
对于您的特定用例,键查询似乎能够让所有用户对产品的价格变化感兴趣,因此您可以为此创建一个表,例如:
create table productSubscriptions ( productId uuid, priceLimit float, createdAt timestamp, email text, primary key (productId,priceLimit,createdAt) );
但是,因为您还需要知道用户的所有产品订阅,所以您都需要一个包含相同数据的用户键表:
create table userProductSubscriptions ( email text, productId uuid, priceLimit float, primary key (email, productId) )
有了这两个表,我猜您可以看到,所有主要查询都可以通过单行select完成,插入/删除也很简单,但需要同步修改这两个表。
显然,您需要更多地充实模式以满足您的全部需求,但这将为您提供一个关于如何考虑cassandra模式的示例。
条件更新问题
对于您的条件插入问题,最简单的答案是:如果您确实需要使用UPDATE (在CQL中update和insert几乎相同),则使用update执行此操作,但这是一个非常昂贵的操作,因此请尽可能避免使用它。
对于您的用例,我会将您的产品表分成三部分:
create table products ( category uuid, productId uuid, url text, price float, primary key (category, productId) ) create table productPricingAudit ( productId uuid, date timestamp, price float, primary key (productId, date) ) create table priceScheduler ( day text, checktime timestamp, productId uuid, url text, primary key (day, checktime) )
products 表可以保存完整的目录,可以选择按类别拆分(因此,列出单个类别中的所有产品是单行选择)
productPricingAudit将有一个带有最新价格的插入,不管它是什么,因为这将允许您调试您可能遇到的任何定价问题
priceScheduler保存给定一天要进行的所有检查,按检查时间排序。每当调度程序运行时,它只需在单行上执行一次列范围查询。
使用这样的模式,您不必关心条件更新,只要更新产品价格,即使价格没有变化,也只需执行3次插入。
发布于 2015-02-10 05:52:34
好的,我将尝试回答我自己的问题:在Cassandra中,除了“如果不存在”之外的条件插入在日期,句号是不受支持的。
最接近的是条件更新,但这在我们的场景中不起作用。所以只剩下一个简单的选择:应用程序端逻辑。这意味着您必须阅读前面的条目并对您的应用程序执行决策。明显的缺点是执行两次查询(一次SELECT和一次INSERT),这明显增加了延迟。
然而,这很适合我们的应用程序,因为每次我们执行查询来将所有应该检查的商品排入队列时,我们也可以选择商品的urls及其当前价格。因此,检查最新价格的工人可以决定是否插入,因为他们有当前价格可供比较。
所以..。类似这样的查询将每X分钟执行一次:
SELECT id, url, price FROM products WHERE "nextCheckTime" < now();
// example only, wouldn't even work if nextCheckTime is not part of the PK or index这是在Cassandra集群上执行的一个非常昂贵的操作,因为它必须遍历默认情况下随机存储在不同节点中的所有行。另一个缺点是,我们需要一些关于产品和用户的高级和具体的统计数据。
因此,我们决定在这种特殊情况下,关系数据库将比Cassandra更好地为我们服务。
遗憾的是,我们保留了Cassandra的所有优势(快速插入、易于缩放、内置分片……)并着眼于MySQL集群或主从实现。
https://stackoverflow.com/questions/28412428
复制相似问题