文档
Apache Cassandra 从零到实战
1. 背景与概念
1.1 为什么需要 Cassandra?
传统关系型数据库(如 MySQL)面临单点瓶颈:读写压力集中在主库。Cassandra 采用去中心化设计——所有节点对等,无主从之分。Google BigTable 的宽列模型 + Amazon Dynamo 的分布式哈希 = Cassandra。
1.2 核心概念速查
| 概念 | 类比 SQL | 说明 |
|---|---|---|
| Keyspace | Database | 数据容器,定义复制策略 |
| Table | Table | 列族,实际存储结构 |
| Partition Key | 无直接类比 | 决定数据在哪个节点上 |
| Clustering Key | ORDER BY 字段 | 分区内排序 |
| TTL | 无直接类比 | 数据自动过期时间 |
1.3 数据模型设计原则
Cassandra 建模不是"范式化",而是"查询驱动"。
❌ SQL 思维:先设计实体关系图
✅ CQL 思维:先列出所有查询,反推表结构
规则:
- 一个查询 = 一张表(允许数据冗余)
- WHERE 条件必须命中 Partition Key
- 不使用 JOIN(数据预聚合)
2. 分步实战:构建时序传感器数据平台
场景
某物联网平台需要存储每台设备每分钟的温度读数,需支持:
- 查询某设备最近 N 条记录
- 查询某设备某天的所有读数
- 自动清理 30 天前的旧数据
步骤一:设计表结构
CREATE KEYSPACE iot_data
WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1};
USE iot_data;
CREATE TABLE sensor_readings (
device_id UUID,
date TEXT, -- '2024-09-01'
timestamp TIMESTAMP,
temperature DOUBLE,
humidity DOUBLE,
status TEXT,
PRIMARY KEY ((device_id, date), timestamp)
) WITH CLUSTERING ORDER BY (timestamp DESC)
AND default_time_to_live = 2592000; -- 30天自动过期
设计分析:
(device_id, date)复合分区键——同一设备同一天的数据在同一分区timestamp DESC——最新数据先返回- TTL = 30天——自动清理旧数据
步骤二:模拟数据写入
from cassandra.cluster import Cluster
import uuid, random, time
from datetime import datetime
cluster = Cluster(['127.0.0.1'])
session = cluster.connect('iot_data')
insert_stmt = session.prepare("""
INSERT INTO sensor_readings (device_id, date, timestamp, temperature, humidity, status)
VALUES (?, ?, ?, ?, ?, ?)
""")
device_id = uuid.uuid4()
for i in range(100):
now = datetime.now()
date = now.strftime('%Y-%m-%d')
session.execute(insert_stmt, [
device_id,
date,
now,
round(random.uniform(20, 30), 2),
round(random.uniform(40, 60), 2),
'normal'
])
time.sleep(0.1)
print("写入 100 条数据完成")
步骤三:常见查询
-- 查询某设备最新 10 条记录
SELECT * FROM sensor_readings
WHERE device_id = <UUID> AND date = '2024-09-01'
LIMIT 10;
-- 范围查询(timestamp 是聚簇键,支持范围)
SELECT * FROM sensor_readings
WHERE device_id = <UUID>
AND date = '2024-09-01'
AND timestamp > '2024-09-01T08:00:00'
AND timestamp < '2024-09-01T18:00:00';
-- 跨日期查询(需要查两个分区)
-- 查询某设备最近 3 天的数据(3次查询或使用 IN,但不推荐 IN 跨分区)
3. 思考题
- 为什么 Cassandra 不推荐 ALLOW FILTERING?在什么场景下可以接受?
- 如果设备数量暴增至 100 万台,分区键设计需要如何调整?提示:考虑热点问题。
- TTL 设置为 30 天后,数据是精确在 30 天后删除还是近似?为什么?