首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >卡桑德拉唯一数据选择和分配的最佳数据模型

卡桑德拉唯一数据选择和分配的最佳数据模型
EN

Stack Overflow用户
提问于 2015-04-13 21:25:43
回答 2查看 196关注 0票数 2

对于以下情况,最佳的Cassandra数据模型和查询是什么?

我们的系统负责为我们的烤面包机分配唯一的序列号,每次都是在我们的工厂里创建的。

  • 我们有多种型号的烤面包机,每种型号都由不同的UPC识别。
  • 一个序列号永远不能分配给一个以上的烤面包机模型(特定于UPC)。
  • 按顺序分配序列号并不重要。
  • 至少每天一次,我们需要弄清楚每个UPC还有多少个未分配的序列号。
  • 我们的系统不时地由另一个系统通过它们的UPC大批量提供序列号。

所需业绩:

  • 为UPC查找未分配的序列号必须是快速的.
  • 插入新的序列号不需要太快。
  • 数数不需要太快。

我们的数据集现在大约有1000万个序列号,每年增长约100万。

我们目前正在使用Cassandra 2.0.x,不久将迁移到2.1.x。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-04-16 14:57:46

好吧,我对这件事作了一些思考。在这种情况下,有几件事是很棘手的:

  • 序列号进来,并被分配(但不是马上)。随着每年100万美元的增长,这就相当于每天有2800个新的序列号。排队(当他们进来的时候把他们放在上面,当他们被分配的时候删除他们)将产生很多墓碑(基本上每天2800块)。
  • 有50个UPC涉及1000万个序列号,计算出每个UPC的序列号为200 K(假设均匀分布)。这意味着我们不能将UPC到序列号的关系存储在一个集合中(最大大小为65536项)。

我假设您想知道哪些序列号与哪种型号联系在一起,哪些型号有哪些序列号。为此,我将使用两个查找表:

代码语言:javascript
复制
CREATE TABLE serialNumbersByUPC (
  modelUPC uuid,
  insertTime timeuuid,
  serialNumber text,
  PRIMARY KEY (modelUPC,insertTime))
WITH CLUSTERING ORDER BY (insertTime DESC);

CREATE TABLE UPCsBySerialNumbers (
  modelUPC uuid
  insertTime timeuuid,
  serialNumber text,
  PRIMARY KEY (serialNumber));

请注意,您也可以使用serialNumbersByUPC作为集群键(而不是insertTime)来对serialNumber进行键设置。但是timeuuids是唯一的(因此在serialNumbers上不会发生冲突),通过insertTime进行集群还有一个好处,允许您按日期/时间进行排序。当然,在为UPC分配序列号时,您需要确保插入到这两个表中。

对于未分配的序列号,最好使用像HornetQRabbitMQ这样的排队系统。这样,您就可以从队列中取出新的序列号,并根据需要分配它们。我提出这个建议的原因是,使用Cassandra来排队的瞬态数据已经被确认为反模式。

当然,您可以决定不注意上述警告,并坚持使用Cassandra作为该功能。如果是这样的话,那么我将用Cassandra存储未分配的序列号:

代码语言:javascript
复制
CREATE TABLE unassignedSerialNumbers (
  dateBucket bigint,
  serialNumber text,
  insertTime timeuuid,
  PRIMARY KEY ((dateBucket),insertTime))
WITH compaction = {'class': 'org.apache.cassandra.db.compaction.DateTieredCompactionStrategy'}
AND gc_grace_seconds = 86400;

关于这个解决方案的一些事情:

  • 我在datebucket上进行分区,因为我不知道您分配每天进来的2800序列号的速度有多快。您可能只想查询今天或昨天输入的数字。我创建它是作为一个bigint,但您可以使用任何大小的桶(例如:"20150416“将隔断序列号的到来,2015年4月16日)。
  • 如果您发现分配序列号的速度足够快,不需要通过datebucket进行分区,那么我就不会担心那个表会变得足够大,从而影响查询性能。当然,您的删除将创建墓碑,您的查询将不得不面对,但这应该有助于我的最后两点。
  • 我在insertTime上进行聚类的原因与在serialNumbersByUPC表中的原因相同。
  • 这张桌子我用的是DateTieredCompactionStrategy。此策略将将同时写入的行保存在相同的SSTABLE文件中。在删除和写入新数据时,这对性能非常重要。
  • gc_grace_seconds被设置为1天而不是10天,这将迫使被刻在墓碑上的行每天被垃圾收集。此设置的缺点是,如果有一个节点下降,则需要在其下线后1天内将其带回来,以获取删除内容。如果你不这样做,你将需要运行一个完整的修复或冒险删除的序列号“从死后回来”。

您还需要在DateTieredCompactionStrategy上阅读。可能还有一些其他的选择,可能对你来说是有意义的。

如果你有什么问题,或者我遗漏了什么,请告诉我。

票数 2
EN

Stack Overflow用户

发布于 2015-04-15 17:37:45

这个怎么样:

有一个包含未分配序列号的表,称之为“未分配”。当你被提供新的序列号时,它们会插入到“未分配”中。UPC编号是分区键,序列号可以是群集列。

然后有另一个表名为“指定”。在构建烤面包机时,可以从未分配的表中随机获取序列号,并尝试使用insert上的“如果不存在”子句将其插入指定的表中。这确保一个序列号只分配一次,以防您运行多个进程。

如果插入成功,则进程将返回并从未分配的表中删除序列号。如果插入由于已经存在的数字而失败,则随机选择不同的数字并尝试该数字,直到得到成功的数字为止。

要获取一个序列号来尝试插入,您可以从限制为100的适当未分配的UPC分区中进行选择,然后随机选择您返回的序列号之一(这样,如果您有多个进程,它们就不会在insert尝试中都尝试相同的编号)。并且在一个分区内限制100将非常快。

现在,要获得未分配数字的计数,可以为未分配表中的每个UPC分区执行选择计数(*),但是如果有太多行,则可能会超时。因此,您可以有第三个表的计数器列和只是增量和减少,因为序列号被添加和使用。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29615391

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档