Cassandra 使用中遇到一个数据模型该怎么建的问题

2016-04-07 00:56:26 +08:00
 oldcai

http://www.datastax.com/dev/blog/basic-rules-of-cassandra-data-modeling

官方给的建议有两点:

  1. Spread Data Evenly Around the Cluster 写数据分布均匀
  2. Minimize the Number of Partitions Read 查询涉及最少分片

也给出了一些使用举例了啦,读的时候以为大概知道要领了,结果下地干活的时候发现然而并没有。。

现在我遇到个问题,逻辑类似 Page Rank, score 通过 follow 关系传递给下一个人,然后不断计算到收敛。需要按从高到低排序。

假设有几亿用户,并且好友关系复杂,这个 score 是一个会比较频繁更新的字段。

为了数据均匀,我用比如 username 来做分区键,会导致查询查的时候分区变得随机;

为了查询的时候结果更集中,我用 score 来做分区键,这样会导致作为分区键的值经常变化。

虽然这个文档中没有提到分区键频繁变化会有什么后果,但是可以想象,根据这个分区键来作为划分 cluster 节点的值,会导致数据不断被转移,显然是低效的。

那么我能想到的解决的办法有两个:

  1. 加一个 score 的区间,按这个字段作为分区键,减少写入时数据在节点间的移动
  2. 建立一个零时表,用来缓存一次排序结果,这个表中的 score 不作改动

想请教有没有更好的 trade off.

821 次点击
所在节点    数据库
9 条回复
david2016
2016-04-07 12:44:11 +08:00
为什么不用 Hbase
oldcai
2016-04-07 12:52:47 +08:00
@david2016
只要是分布式数据库都会遇到这个问题吧?
更多选择更多欢笑不是吗?
HBase 也考虑过。
david2016
2016-04-07 13:00:12 +08:00
@oldcai 恩恩 我也是最近刚开始研究 HBase
lszwycn
2016-04-07 14:31:58 +08:00
@david2016 这种回答......为什么用 HBase?
david2016
2016-04-07 15:23:50 +08:00
@lszwycn 不好意思,因为我也是刚开始研究面对列的数据库,因为 Cassandra 与 HBase 都是面对列,并且据我了解 HBase 好像应用的更广泛些吧 我选择 HBase 是因为搭配 Hadoop 其他组件一起使用。如回答引起歧义 请谅解
mko0okmko0
2016-04-07 23:16:41 +08:00
如果是技术选型,就把数据都丢进目标内跑查询看耗时与资源消耗程度.选表现较好的留作主力了.
这问题只发生在想兼顾读写能力和查询性能并只用一种资料库仓储设计才比较会发生吧?

你的计算大约多久需要一次?还是用户某行为就需要立刻计算?
如果是某段时间做一次并以此结果做某后续应用.那我会选写入平均.
如果是软即时计算,那就要稍微设计以计算速度为要点,放弃写入性能.
写入性能可以靠其他列队系统(MQ)先写入到列队,然后再用其他写入服务写入到 Cassandra 内.如下:

用户上传 -> MQ(可能是集群)收 -> 某循环程式 -> Cassandra
<- 到就回应已经存入 从 MQ 取纪录

收到删除要求就删 <- 收到写入确 <- 全部集群都写入完成后回应完成
除该纪录 认后从 MQ 删
除这笔纪录

另一台服务(有可能是一台主机或是跟某些服务安装在一起),
跑一个循环脚本(程式语言不限制能动很稳就好):从 MQ 取得纪录写到 Cassandra 并确认写入完成回应,循环执行.
这里的认为可用完全同步,虽然过半写入回应会有较高的写性能,但我们已经放弃写入性能了,而且这样可以减少最终一致的问题发生率.
如果 MQ 回应无纪录,等 200ms 再循环(太快再循环会消耗性能又没用).
总之这个"循环程式"不能挂.你需要另一个"监察程式"检查这个"循环程式"是否挂了,然后"监察程式"再次启动"循环脚本"

以上模式很多资料库都适合用,
反正都放弃 Cassandra 的写性能了,反正这模式结果也是最终一致了(最后几秒的纪录误差),
Cassandra 其实并不是这个仓储 /计算模式首选的资料库了,
至于哪些资料库在你的业务需求内有更好的查询 /统计性能,
请你实测了(结果还是回到我开头的第一行)

手动打造大数据仓储与计算系统的码农一点点分享.
mko0okmko0
2016-04-07 23:30:43 +08:00
排版跑了,底线请用空白置换:

用户上传 ] -> [ MQ(可能是集群)收_] -> [某循环程式从 MQ 取纪录 ] -> [______Cassandra___________ ]
________] <- [ 到就回应已经存入,_]___[____________________]___[_________________________ ]
____________[收到删除要求就删__]<-_[收到写入确认后从 MQ 删_]<- [全部集群都写入完成后回应完成]
____________[除该纪录_________]___[除这笔纪录___________]
oldcai
2016-04-08 09:35:16 +08:00
@mko0okmko0 感谢分享,但是因为选择 cassandra 的原因就是写入性能的提升和扩展后性能的线性。
不过你说的需要靠对比这一点很对,就是相对麻烦一点,消耗的时间也不短,但是鉴于需求似乎比较特殊,少有参照案例来借鉴,也确实是一种行之有效的办法。
我的需求里面,计算一整遍后可以用固定一段时间,比如一周。但是平时也算是读写都密集了吧,因为需要记录新的 score 和新用户注册,以及随机读取用户 score 、按 score 排序。所以我还需要再考虑一下。
mko0okmko0
2016-04-08 09:46:41 +08:00
@oldcai
看起来你也只是某段时间计算那一次,如果这次的计算不赶时间,
那我会选写入平均.过半写入回应.

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/269117

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX