为了好玩,我正在构建一个高音扬声器克隆,以便更好地理解C *
我所看到的所有建议的C *方案都使用或多或少相同的建模技术。问题在于我对以这种方式建模推特时间线的可扩展性表示怀疑。
问题: 如果我有一个非常受欢迎的用户A(摇滚明星)或更多,后面跟着10k +用户,会发生什么? 每次userA发布推文时,我们都必须为他的每个粉丝插入10k +推文的时间表。
问题: 这个模型真的会扩展吗? 任何人都可以建议我一种可以真正扩展的时间轴建模的替代方法吗?
C *架构:
CREATE TABLE users (
uname text, -- UserA
followers set, -- Users who follow userA
following set, -- UserA is following userX
PRIMARY KEY (uname)
);
-- View of tweets created by user
CREATE TABLE userline (
tweetid timeuuid,
uname text,
body text,
PRIMARY KEY(uname, tweetid)
);
-- View of tweets created by user, and users he/she follows
CREATE TABLE timeline (
uname text,
tweetid timeuuid,
posted_by text,
body text,
PRIMARY KEY(uname, tweetid)
);
-- Example of UserA posting a tweet:
-- BATCH START
-- Store the tweet in the tweets
INSERT INTO tweets (tweetid, uname, body) VALUES (now(), 'userA', 'Test tweet #1');
-- Store the tweet in this users userline
INSERT INTO userline (uname, tweetid, body) VALUES ('userA', now(), 'Test tweet #1');
-- Store the tweet in this users timeline
INSERT INTO timeline (uname, tweetid, posted_by, body) VALUES ('userA', now(), 'userA', 'Test tweet #1');
-- Store the tweet in the public timeline
INSERT INTO timeline (uname, tweetid, posted_by, body) VALUES ('#PUBLIC', now(), 'userA', 'Test tweet #1');
-- Insert the tweet into follower timelines
-- findUserFollowers = SELECT followers FROM users WHERE uname = 'userA';
for (String follower : findUserFollowers('userA')) {
INSERT INTO timeline (uname, tweetid, posted_by, body) VALUES (follower, now(), 'userA', 'Test tweet #1');
}
-- BATCH END
提前感谢任何建议。
答案 0 :(得分:0)
在我看来,您概述的架构或类似的架构最好给出用例(请参阅用户X订阅的最新推文+查看我的推文)。
然而,有两个陷阱。我不认为Twitter使用Cassandra存储推文,可能与您开始考虑的原因相同。在Cassandra上运行这个Feed似乎不是一个好主意,因为你不想永远保留其他人的推文的无数副本,而是为每个用户保留某种滑动窗口(大多数用户不会我猜测,从他们的Feed的顶部读取1000条推文。所以我们讨论的是队列,以及在某些情况下基本上实时更新的队列。卡桑德拉只能通过一些强制来支持这种模式。我认为它不是为大规模流失而设计的。
在生产中,可能会选择另一个对队列提供更好支持的数据库 - 可能是像列表支持的分片Redis那样。
对于您提供的示例,问题并不像看起来那么糟糕,因为您不需要在同步批处理中执行此更新。您可以发布到作者的列表,快速返回,然后使用在群集中运行的异步工作程序执行所有其他更新,使用尽力而为的QoS推送更新。
最后,既然您已经询问了替代方案,那么这是我能想到的变体。它可能在概念上更接近我提到的队列,但在引擎盖下它会遇到很多与大量数据流失相关的问题。
CREATE TABLE users(
uname text,
mru_timeline_slot int,
followers set,
following set,
PRIMARY KEY (uname)
);
// circular buffer: keep at most X slots for every user.
CREATE TABLE timeline_most_recent(
uname text,
timeline_slot int,
tweeted timeuuid,
posted_by text,
body text,
PRIMARY KEY(uname, timeline_slot)
);