如何在非规范化NoSQL数据库(Cassandra/ScyllaDB)中保持表数据同步?
1. 为何不单独设计comments实体表?
Cassandra/ScyllaDB这类分布式NoSQL的核心设计逻辑是查询优先,而非传统关系型数据库的「实体优先」。如果业务中没有「通过commentId单独查询单条评论」这类需求,单独的comments实体表完全是冗余的。
实际业务里,评论的常见查询场景无非两种:「查看某用户的所有评论」「查看某视频的所有评论」,comments_by_user和comments_by_video这两张表正是为了直接匹配这两类查询而设计的——它们能让查询直接命中目标数据,避免了关系型数据库中低效的关联操作。在分布式系统中,用可控的数据冗余换取查询性能,是完全合理的设计选择。
2. 如何保证两张表的commentId一致?
没错,必须先把timeuuid预先生成并赋值给变量,再用这个变量执行两次插入操作。因为每次调用timeuuid()都会生成全新的UUID,直接在两次INSERT里调用肯定会得到不同的值。
另外,推荐把这两个插入操作放到**批处理(BATCH)**中执行,这样既能保证ID一致,还能确保两个操作要么全部成功,要么全部失败,避免出现数据不一致的情况。示例代码如下:
-- 先在应用层生成timeuuid,比如用编程语言的UUID工具类 var myuuid = timeuuid(); BEGIN BATCH INSERT INTO comments_by_user(user_id, comment_id, video_id, content, created_at) VALUES ('user_1001', myuuid, 'video_2001', '这个视频干货满满!', toTimestamp(myuuid)); INSERT INTO comments_by_video(video_id, comment_id, user_id, content, created_at) VALUES ('video_2001', myuuid, 'user_1001', '这个视频干货满满!', toTimestamp(myuuid)); APPLY BATCH;
注意:批处理不要滥用,只用于这种强关联的小批量操作,避免影响集群性能。
3. 若存在comments表,是否需要先插它再插另外两个表?
首先,要不要建comments表,取决于你有没有「通过commentId查询单条评论」的业务需求——如果没有,完全没必要多此一举。
如果确实需要comments表,也不需要先插它再获取ID。正确的做法是:在应用层提前生成唯一的commentId,然后用同一个ID同时插入三张表(comments、comments_by_user、comments_by_video)。同样可以用批处理来保证三个操作的原子性,避免出现部分插入成功的情况。
内容的提问来源于stack exchange,提问作者Eddy Freeman

