📖 数据密集型设计

Cassandra分布式存储与一致性

深入探讨Cassandra的分布式架构与一致性模型

一、Cassandra概述

Cassandra是一款高度可扩展的分布式NoSQL数据库,设计用于处理大量数据和高并发读写。Cassandra采用P2P架构,没有单点故障,支持线性水平扩展。

二、Cassandra架构

2.1 节点架构

Cassandra集群由多个节点组成,每个节点都是平等的,没有主从之分:

graph TD A[节点1] --> B[节点2] A --> C[节点3] A --> D[节点4] B --> C B --> D C --> D E[客户端] --> A E --> B E --> C E --> D

2.2 数据分布

Cassandra使用一致性哈希将数据分布到各个节点:

graph LR A[Token Ring] --> B[节点1: 0-100] A --> C[节点2: 101-200] A --> D[节点3: 201-300] A --> E[节点4: 301-400] F[数据Key] --> A A --> G{计算Token} G --> B G --> C G --> D G --> E

三、Cassandra一致性模型

3.1 一致性级别

Cassandra支持可配置的一致性级别,在一致性和可用性之间进行权衡:

一致性级别 含义 适用场景
ONE 写入一个节点 低延迟写入
QUORUM 写入多数节点 平衡一致性和性能
ALL 写入所有节点 最高一致性
LOCAL_QUORUM 数据中心内多数 多数据中心

3.2 CAP理论

Cassandra在CAP理论中选择AP(可用性和分区容错性),牺牲部分一致性:

graph TD A[CAP理论] --> B[一致性C] A --> C[可用性A] A --> D[分区容错P] B --> B1[所有节点数据一致] C --> C1[任何时候都能响应] D --> D1[网络分区时继续工作] E[Cassandra选择] --> C E --> D E --> F[牺牲部分C]

四、Cassandra数据建模

4.1 表设计原则

Cassandra的数据建模与关系型数据库不同,需要根据查询模式设计:

  • 查询优先:先确定查询模式,再设计表结构
  • 反规范化:允许数据冗余,减少JOIN
  • 分区键:合理选择分区键,均匀分布数据
  • 聚类列:聚类列决定分区内数据排序

4.2 创建表

CREATE TABLE user_activity (
    user_id UUID,
    activity_date DATE,
    activity_time TIME,
    activity_type TEXT,
    details TEXT,
    PRIMARY KEY (user_id, activity_date, activity_time)
) WITH CLUSTERING ORDER BY (activity_date DESC, activity_time DESC);

4.3 复合主键

Cassandra的主键由分区键和聚类列组成:

-- 分区键: user_id
-- 聚类列: activity_date, activity_time
PRIMARY KEY (user_id, activity_date, activity_time)

五、Cassandra读写操作

5.1 写入流程

// Java驱动写入示例
PreparedStatement stmt = session.prepare(
    "INSERT INTO user_activity (user_id, activity_date, activity_time, activity_type, details) " +
    "VALUES (?, ?, ?, ?, ?)"
);

BoundStatement bound = stmt.bind(
    UUID.randomUUID(),
    LocalDate.now(),
    LocalTime.now(),
    "login",
    "User login from web"
);

session.execute(bound);

5.2 读取流程

// 按分区键查询
ResultSet rs = session.execute(
    "SELECT * FROM user_activity WHERE user_id = ?",
    userId
);

// 按分区键和聚类列查询
ResultSet rs = session.execute(
    "SELECT * FROM user_activity WHERE user_id = ? AND activity_date = ?",
    userId, date
);

六、Cassandra副本策略

6.1 SimpleStrategy

简单副本策略,适用于单数据中心:

CREATE KEYSPACE mykeyspace WITH REPLICATION = {
    'class': 'SimpleStrategy',
    'replication_factor': 3
};

6.2 NetworkTopologyStrategy

网络拓扑策略,适用于多数据中心:

CREATE KEYSPACE mykeyspace WITH REPLICATION = {
    'class': 'NetworkTopologyStrategy',
    'DC1': 3,
    'DC2': 2
};

七、Cassandra性能优化

7.1 分区键选择

选择基数足够高的分区键,避免热点分区:

-- 好的分区键
user_id (UUID)

-- 不好的分区键
country (基数低,可能热点)

7.2 数据模型优化

根据查询模式设计数据模型,避免全表扫描:

-- 反规范化示例
CREATE TABLE user_with_posts (
    user_id UUID PRIMARY KEY,
    username TEXT,
    email TEXT,
    posts LIST<FROZEN<post>>
);

7.3 压缩与缓存

Cassandra支持多种压缩算法和缓存策略:

CREATE TABLE user_activity (
    ...
) WITH compression = {
    'class': 'LZ4Compressor'
};

八、Cassandra监控与运维

8.1 监控指标

  • 读写延迟:平均读写延迟
  • 节点状态:节点健康状态
  • 副本状态:副本同步状态
  • 压缩率:数据压缩效果

8.2 监控工具

  • nodetool:命令行工具
  • Prometheus + Grafana:开源监控
  • DataStax OpsCenter:官方监控工具

九、Cassandra与其他数据库对比

特性 Cassandra MongoDB MySQL
分布式 原生分布式 支持分片 主从复制
一致性 可调一致性 最终一致 强一致性
扩展性 线性扩展 分片扩展 有限扩展
查询灵活性 有限 灵活 灵活

十、总结

Cassandra是一款专为大规模分布式场景设计的数据库,适合需要高可用性和线性扩展的应用。掌握Cassandra的架构和数据建模方法,能够构建高性能、可扩展的数据密集型应用。