题目
设计一个Cassandra数据模型用于存储用户事件日志
信息
- 类型:问答
- 难度:⭐⭐
考点
数据建模,分区键设计,查询模式,时间序列数据,性能优化
快速回答
核心设计要点:
- 使用复合主键:
(event_date, user_id, event_time)作为主键 - 分区键:
event_date(按天分区) - 聚类键:
user_id和event_time(降序排序) - TTL设置:根据合规要求自动过期数据
- 反范式化:直接存储常用查询字段
1. 需求场景
需要存储用户行为事件(如点击、登录),支持以下查询:
- 按用户ID和时间范围查询事件
- 按事件类型聚合每日数据
- 自动清理过期日志(如保留30天)
2. 数据模型设计
CREATE TABLE user_events (
event_date DATE, -- 分区键
user_id UUID,
event_time TIMESTAMP,
event_type TEXT,
device_id TEXT,
properties MAP<TEXT, TEXT>,
PRIMARY KEY ((event_date), user_id, event_time)
) WITH CLUSTERING ORDER BY (user_id ASC, event_time DESC);3. 设计原理
- 分区键设计:
event_date确保每天数据在物理上连续存储,避免热点 - 聚类键:
user_id实现用户数据局部性,event_time DESC使最新事件优先 - TTL设置:在写入时指定
USING TTL 2592000(30天)自动过期
4. 查询示例
按用户查询24小时内事件:
SELECT * FROM user_events
WHERE event_date = '2023-10-01'
AND user_id = 123e4567
AND event_time > '2023-10-01 00:00:00';5. 最佳实践
- 避免宽分区:监控分区大小(建议 <100MB),可通过增加分区粒度(如每小时)解决
- 批量写入:使用
UNLOGGED BATCH写入同分区数据 - 反范式化:为高频查询创建额外表(如按事件类型聚合的物化视图)
6. 常见错误
- 错误:使用
TIMESTAMP作为分区键 → 导致无限分区增长 - 错误:过度使用二级索引 → 应改用新查询表
- 错误:忽略TTL → 磁盘空间爆炸
7. 扩展知识
- 时间窗口压缩策略:
TimeWindowCompactionStrategy (TWCS)优化时间序列数据 - 分页查询:使用
token()函数跨分区分页 - 聚合处理:配合Apache Spark进行复杂分析