Apache Cassandra 入门:不只是“记录日志”的数据库
在业务系统里,我们经常会遇到这样一类数据:访问日志、用户操作记录、聊天消息、设备上报、监控指标……它们增长很快、写入很频繁,而且服务不能轻易停机。
这时,传统关系型数据库(例如 MySQL)未必是最合适的选择。Apache Cassandra 就是一款为这类场景设计的分布式 NoSQL 数据库。
Cassandra 是什么?
Cassandra 是一个开源的分布式数据库。简单理解,它可以把数据分散存到多台服务器上,并让这些服务器一起对外提供读写服务。
它的几个核心特点是:
- 可以横向扩展:数据量或访问量增加时,增加服务器即可扩容。
- 高可用:某一台服务器故障,其他节点通常仍能继续服务。
- 擅长高并发写入:很适合持续不断产生大量新数据的业务。
- 支持多机房复制:可以把数据复制到不同地域,提升容灾能力。
因此,Cassandra 最常见的用途之一确实是记录日志,但它的应用范围比日志更广。
Cassandra 适合哪些场景?
下面这些场景通常很适合 Cassandra:
-
日志与审计记录 例如用户登录日志、接口调用日志、后台操作记录。它们通常写入多、查询方式固定,例如“查询某个用户最近 30 天的操作”。
-
物联网数据 大量设备持续上报温度、位置、电量、运行状态等数据。设备数量多、上报频率高,很符合 Cassandra 的写入特点。
-
聊天和消息记录 例如按会话查询最近消息、按用户查询通知记录。这类数据量大,通常也是按固定维度读取。
-
监控指标和时间序列数据 比如服务器 CPU、内存、请求量、延迟等。数据按时间不断追加,并且经常按“某台机器 + 某段时间”查询。
-
订单或业务状态轨迹 Cassandra 不一定适合作为交易订单的唯一主库,但很适合保存订单状态变化、事件流或查询副本。
它和 MySQL 有什么区别?
MySQL 的设计重点是关系、事务和灵活查询。你可以通过 SQL 做复杂筛选、关联查询和统计。
Cassandra 的思路不同:它更强调“提前知道怎么查,再按查询方式设计数据”。
| 对比项 | MySQL | Cassandra |
|---|---|---|
| 数据模型 | 关系型表结构 | 宽列 NoSQL 模型 |
| 擅长场景 | 事务、关联、复杂查询 | 海量数据、高并发读写 |
| 扩容方式 | 通常以纵向扩容为主 | 天然支持增加节点横向扩容 |
| 查询方式 | 灵活 SQL 查询 | 围绕主键和既定查询路径设计 |
| 一致性 | 默认强一致事务能力较强 | 可按业务选择一致性级别 |
| 联表查询 | 支持 JOIN | 不支持 JOIN |
这并不表示 Cassandra 比 MySQL 更好。它们解决的问题不同。
如果你需要支付扣款、库存扣减、复杂报表、多个表之间的强一致事务,MySQL、PostgreSQL 这类关系型数据库往往更适合。
如果你需要稳定地写入几十亿条日志、设备数据或消息记录,并且希望随时加机器扩容,Cassandra 就很有优势。
Cassandra 的几个核心概念
1. Cluster:集群
Cluster 是由多台 Cassandra 服务器组成的整体。每台服务器叫作一个节点(Node)。
Cassandra 没有传统意义上的“主库”和“从库”。节点之间地位相对平等,数据会根据规则分布在不同节点上。
2. Keyspace:类似数据库
Keyspace 可以理解为 MySQL 中的数据库,但它还会定义数据复制策略,例如数据需要保存几份、复制到哪些数据中心。
CREATE KEYSPACE demo
WITH replication = {
'class': 'SimpleStrategy',
'replication_factor': 3
};
上面的 replication_factor: 3 表示每份数据保存 3 个副本。生产环境通常会使用更适合多数据中心的复制策略。
3. Table:表
Cassandra 也有表,但表设计方式和关系型数据库不同。它不适合先建一张“万能大表”,然后靠各种条件自由查询。
更常见的做法是:一个查询需求,对应一张合适的表。
4. Partition Key:分区键
分区键决定一条数据大致会落在哪些节点上。它是 Cassandra 数据建模中最重要的概念之一。
例如日志表可以按用户分区:
CREATE TABLE demo.user_logs (
user_id text,
log_time timestamp,
action text,
detail text,
PRIMARY KEY (user_id, log_time)
);
这里:
user_id是分区键;log_time是聚簇列,用来控制同一个用户的数据排序;- 查询时适合使用
user_id,并按时间范围读取。
一个最小示例:保存用户操作日志
假设我们要记录用户操作日志,并查询某位用户最近的操作。
先进入 Keyspace:
USE demo;
创建表:
CREATE TABLE user_logs (
user_id text,
log_time timestamp,
action text,
detail text,
PRIMARY KEY (user_id, log_time)
) WITH CLUSTERING ORDER BY (log_time DESC);
插入一条日志:
INSERT INTO user_logs (user_id, log_time, action, detail)
VALUES (
'u_1001',
toTimestamp(now()),
'LOGIN',
'用户通过密码登录'
);
查询该用户最近的日志:
SELECT * FROM user_logs
WHERE user_id = 'u_1001'
LIMIT 20;
这个设计非常适合“按用户查操作历史”。但如果后续还要频繁按 action 查询,例如“查所有登录行为”,就不能直接依赖这张表,通常需要额外建立一张面向该查询的表。
Cassandra 数据建模的关键原则
使用 Cassandra 时,最容易踩坑的一点是:拿着 MySQL 的建模思维直接套用。
在 Cassandra 中,建议记住下面三条原则:
-
先设计查询,再设计表 先问自己:“系统需要按什么条件查数据?”然后围绕这些查询路径建表。
-
避免跨分区查询 查询最好带上分区键。没有分区键的大范围扫描,通常性能较差或无法执行。
-
控制单个分区的大小 例如把所有日志都放进一个分区,会造成热点和性能问题。时间序列数据常见做法是按“用户 + 日期”或“设备 + 月份”分区。
例如,设备监控数据可以这样设计:
PRIMARY KEY ((device_id, record_date), record_time)
这样同一设备每天的数据放在一个分区中,既便于按天查询,也避免无限增长。
Cassandra 不适合什么?
Cassandra 并不是万能数据库。以下场景要谨慎使用:
- 需要复杂 JOIN 的业务;
- 需要任意条件组合筛选的数据后台;
- 强依赖多表事务的一致性场景;
- 需要频繁修改数据结构、探索式分析的场景;
- 数据量不大、只有单机或小规模需求的普通业务。
如果只是一个小型系统的后台管理、商品管理或订单管理,先使用 MySQL 往往更简单、更省心。
总结
Cassandra 可以理解为一款面向大规模、高并发和高可用场景的分布式 NoSQL 数据库。
它特别适合日志、消息、监控、设备数据等持续写入的数据;但它要求开发者在建表前就想清楚查询方式。与其说它是“存日志的数据库”,不如说它是“为海量、稳定写入和分布式扩展而设计的数据库”。
入门 Cassandra 时,最值得优先掌握的不是复杂语法,而是这句话:
用查询需求设计表,而不是先设计表再自由查询。