Module 03 · Introducing Apache Cassandra: An Open-Source NoSQL Database
Apache Cassandra Data Model: Part 2Apache Cassandra 数据模型(第二部分)
欢迎观看关于 Apache Cassandra 数据模型 的第二部分视频。在本视频中,您将能够:
- 解释 聚类键(Clustering Keys)是什么,
- 描述 动态表(Dynamic Tables),
- 解释建模数据的基本准则。
聚类键(Clustering Key)
聚类键的作用
在 Cassandra 中,聚类键 是主键的第二部分,用于决定数据在 分区 内的排序方式。分区键决定了数据的本地性,而聚类键则定义了数据在分区内部的排列顺序(升序或降序),并优化了在一个分区内检索相似值的数据。
- 聚类键可以是单列或多列键。
- 在本例中,聚类键由 username 列组成,这意味着数据将在每个分区内按用户名升序排列。
聚类键的优势
聚类键不仅提供了主键的唯一性,还能显著提升 读取查询 的性能。例如,当我们查询某个特定分组下年龄为 32 的用户时,数据将根据年龄分组,然后根据用户名排序,查询时将只读取符合条件的记录,避免了读取大量无关数据。
减少查询数据量的重要性
减少从分区读取的数据量对查询时间至关重要,特别是在大型分区中,Cassandra 可能需要读取数百兆字节的数据才能从几千字节的数据中提供答案。
动态表(Dynamic Table)
动态表 是具有分区键和聚类键的表。这些表根据主键的定义动态增长,随着数据的增加,分区的大小会变化。
动态表的数据插入
当向动态表中插入数据时,Cassandra 会根据 分区键 确定数据存储的位置,并将新数据追加到现有分区中。如果分区中已有多个条目,新的条目将按聚类键的顺序存储。
- 分区 是 Cassandra 存储的最小单位,每个分区的数据总是存储在同一节点上,并在其他节点上有副本。
- 在实际操作中,插入或读取数据时,Cassandra 会通过哈希函数定位到具体的节点。
数据的分布和复制
在 Cassandra 中,数据分布到集群中的不同节点,并根据 复制因子 在多个节点上保持副本。例如,如果一个分区的复制因子为 3,则该分区的数据会有 3 个副本分布在集群中的不同节点上。
建模数据的基本准则
在 Cassandra 中进行数据建模时,以下是几个关键的准则:
选择分区键
- 选择能够起始查询的分区键:分区键应能均匀地分布数据。例如,如果有多个 groupId,并且每个 groupId 的大小差不多,那么 groupId 可以是一个合适的分区键。
- 最小化查询时需要读取的分区数量:Cassandra 将数据分布到多个分区,如果查询需要读取多个分区,则可能需要访问多个节点,从而影响查询性能。理想情况下,我们应该设计主键以便能够仅读取一个分区来完成查询。
优化聚类键
聚类键的设计应根据查询需求,按顺序排列列,以便能最小化读取的数据量。通过合理设计聚类键,能显著提高查询效率。
总结
通过本视频,您学习了:
- 聚类键 用于定义分区内部数据的排序顺序,并可以优化读取性能。
- 动态表 中的数据随着条目的增加而动态增长,分区的大小会随之变化。
- 在 Cassandra 数据建模中,最重要的步骤是根据您的查询需求设计主键,确保尽可能只读取一个分区的数据,从而提高查询效率。
- 构建主键时要考虑 分区键 的均匀分布和 聚类键 的顺序安排,以便最优化数据访问。
核心概念深度解析
1. 聚类键 (Clustering Key) 的威力
在Part 1中,我们知道了聚类键用于在分区内排序。Part 2则深入揭示了它的另一个强大功能:分区内的高效数据检索和过滤。
- 工作机制:
- 在一个分区内(即共享同一个分区键的所有数据),数据行按照聚类键的定义顺序物理存储在磁盘上。
- 这个顺序可以是升序(ASC)或降序(DESC),可以在建表时定义。
- 因为数据是有序的,Cassandra可以像在有序数组中一样进行高效的范围查询和等值查询,而无需扫描整个分区。
- 视频中的例子解析:
- 查询: “给我组ID 12中所有年龄为32的用户。”
- 设计方案:
PRIMARY KEY ((groupid), age, username)- 分区键:
groupid-> 确保查询groupid=12的数据全都在一个节点上的一个分区内。 - 聚类键:
age, username-> 数据在分区内先按age排序,在age相同的情况下再按username排序。
- 分区键:
- 执行过程(架构师视角):
- 查询
WHERE groupid=12 AND age=32。 - 系统定位到存储
groupid=12这个分区的节点。 - 由于数据按
age排序,它可以直接二分查找或快速定位到age=32的数据块。 - 它只需要读取这个特定
age值对应的连续数据块(可能只有几KB),而无需读取整个可能包含各个年龄段用户的、巨大的分区(可能几百MB)。 - 这就是所谓的 “减少分区内数据读取量” ,是优化查询性能的关键。
- 查询
2. 动态表 (Dynamic Table) 的再认识
- 定义: 主键包含聚类键的表。
- 特点: 每个分区(分区键相同)可以包含多行数据(由不同的聚类键值区分)。分区的大小会随着数据的插入而动态增长。
- 架构师警示: 必须警惕 “超大分区(Large Partitions)” 问题。如果一个分区的数据无限增长(例如,一个非常活跃的聊天群的所有消息都放在一个分区里),当这个分区的大小达到MB甚至GB级别时,会对读写性能、压缩和修复操作造成巨大压力。设计时必须估算一个分区的最大可能容量。
3. 数据建模的核心准则(黄金法则)
这部分是视频的精华,也是你作为架构师必须内化的设计原则。
- 准则一:分区键的选择 —— 均匀分布与查询入口
- 必须支持查询: 你的查询的
WHERE子句必须包含分区键(等于或IN操作),这是铁律。 - 必须避免热点: 分区键的基数(不同取值的数量)要足够高,以确保数据能均匀分布到集群的所有节点上。例如,用
user_id(高基数)比用country_code(低基数)做分区键要好得多,否则所有中国用户的数据都会堆在同一个节点上,形成热点。
- 必须支持查询: 你的查询的
- 准则二:最小化分区读取数量 —— “One Query, One Partition”
- 理想目标: 一个查询最好只从一个分区中读取数据。这意味着只需要访问集群中的一个节点(及其副本)就能得到答案,延迟最低,性能最高。
- 反面模式: 如果查询需要扫描多个分区(例如,
WHERE age = 25,但age不是分区键),那么协调节点就需要向集群中所有节点(或大量节点)发起请求,收集结果后再聚合。这会产生极高的延迟和协调开销,在Cassandra中应极力避免。
- 准则三:利用聚类键优化分区内查询
- 在满足“一个查询一个分区”的基础上,使用聚类键来进一步缩小需要扫描的数据范围。如上面的例子,通过
age和username聚类,可以快速定位到分区内一个更小的、连续的数据片段。
- 在满足“一个查询一个分区”的基础上,使用聚类键来进一步缩小需要扫描的数据范围。如上面的例子,通过
总结给你(系统架构师备考者)
Cassandra的数据建模是一个 “目的导向” 的逆向过程,与你熟悉的RDBMS范式化设计截然不同。请牢记以下流程:
- 起点: 从应用程序的查询需求出发。列出所有必须支持的查询语句。
- 设计: 为每个查询设计最佳的表结构。这意味着通常会有大量的数据冗余,同一个数据可能会出现在多张不同的表中,以支持不同的查询模式。这是用空间换时间和扩展性的经典权衡。
- 实现:
- 根据查询的
WHERE条件确定分区键。确保它能直接定位到数据所在节点,且数据分布均匀。 - 根据查询的排序(
ORDER BY)和过滤(WHERE中对非分区键字段的条件)需求确定聚类键。利用它来组织分区内数据,实现高效检索。
- 根据查询的
- 校验: 始终问自己:这个设计是否遵循了 “一个查询,一个分区” 的黄金法则?是否能避免超大分区?
掌握这些思想,你就能设计出真正高性能、可扩展的Cassandra数据模型,从而为大型分布式系统打下坚实的基础。这是系统架构师的核心技能之一。