面试题答案
一键面试数据建模
- 关注关系表:
- 设计一个表用于存储关注关系,例如
following_relations
。以关注者的ID作为分区键,被关注者的ID作为聚类键。这样可以快速查询某个用户关注了哪些人。
CREATE TABLE following_relations ( follower_id UUID, following_id UUID, PRIMARY KEY (follower_id, following_id) );
- 设计一个表用于存储关注关系,例如
- 动态信息表:
- 设计一个表用于存储用户发布的动态信息,例如
user_posts
。以用户ID作为分区键,动态的时间戳作为聚类键(方便按时间顺序查询动态)。同时可以添加动态的具体内容等其他列。
CREATE TABLE user_posts ( user_id UUID, post_timestamp TIMESTAMP, post_content TEXT, PRIMARY KEY (user_id, post_timestamp) );
- 设计一个表用于存储用户发布的动态信息,例如
- 粉丝动态计数表:
- 为了快速获取每个用户的动态发布数量,设计一个表
user_post_count
。以用户ID作为分区键,同时添加一个列post_count
记录发布动态的数量。
CREATE TABLE user_post_count ( user_id UUID, post_count COUNTER, PRIMARY KEY (user_id) );
- 每次用户发布新动态时,在
user_posts
表插入记录的同时,在user_post_count
表中增加post_count
的值。
- 为了快速获取每个用户的动态发布数量,设计一个表
查询语句优化
- 获取粉丝列表:
- 首先通过
following_relations
表反向查询,获取指定用户的所有粉丝。由于following_relations
表是以关注者ID为分区键,所以需要全表扫描或使用二级索引。为了避免全表扫描,可以创建一个反向索引表followers_relations
。
CREATE TABLE followers_relations ( following_id UUID, follower_id UUID, PRIMARY KEY (following_id, follower_id) );
- 查询粉丝列表的语句:
SELECT follower_id FROM followers_relations WHERE following_id =?;
- 首先通过
- 获取粉丝动态发布数量:
- 对于每个粉丝,从
user_post_count
表中获取其动态发布数量。
SELECT post_count FROM user_post_count WHERE user_id IN (?,?,?,...);
- 这里使用
IN
操作符,注意IN
操作符中的值数量不能过多,否则可能影响性能。可以分批查询。
- 对于每个粉丝,从
- 排序并取前10:
- 将获取到的粉丝及其动态发布数量在应用程序中进行排序,取前10个结果。如果数据量较大,可以在数据库层面进行排序。在Cassandra 3.0及以上版本,可以使用物化视图。
- 创建物化视图
top_10_fan_post_count
:
CREATE MATERIALIZED VIEW top_10_fan_post_count AS SELECT following_id, follower_id, post_count FROM followers_relations JOIN user_post_count ON followers_relations.follower_id = user_post_count.user_id WHERE following_id IS NOT NULL AND post_count IS NOT NULL PRIMARY KEY (following_id, post_count DESC, follower_id);
- 查询语句:
SELECT follower_id, post_count FROM top_10_fan_post_count WHERE following_id =? LIMIT 10;
缓存策略
- 应用层缓存:
- 在应用程序中使用缓存,例如使用Memcached或Redis。对于频繁查询的用户,可以将其粉丝中发布动态数量最多的前10个用户的结果缓存起来。缓存的Key可以是用户ID,Value是查询结果。
- 设置合适的缓存过期时间,例如几分钟到几小时不等,具体根据数据更新频率而定。如果数据更新不频繁,可以设置较长的过期时间。
- 数据库层缓存:
- Cassandra本身有一些缓存机制,如行缓存(Row Cache)和键缓存(Key Cache)。可以适当调整这些缓存的参数,提高查询性能。例如增加行缓存的大小,以缓存更多的查询结果。
- 配置行缓存:
row_cache: enabled: true size_in_mb: 2048 warmup: true
应对高并发场景
- 负载均衡:
- 使用负载均衡器,如Nginx或HAProxy,将高并发请求均匀分配到多个Cassandra节点上。这样可以避免单个节点负载过高。
- 配置负载均衡器的健康检查机制,及时发现并剔除故障节点。
- 读写分离:
- 对于读多写少的场景,可以采用读写分离策略。将读请求发送到副本节点,写请求发送到主节点。Cassandra支持灵活的复制因子和一致性级别设置,可以根据实际需求调整。
- 例如,对于读请求,设置一致性级别为
ONE
,以提高读取性能;对于写请求,设置一致性级别为QUORUM
,以保证数据的一致性。
- 异步处理:
- 对于一些非关键的操作,如更新粉丝动态计数表,可以采用异步处理。使用消息队列,如Kafka,将更新操作发送到队列中,由后台任务异步处理。这样可以避免高并发时对主业务流程的影响。