1. Overview
1.概述
Data distribution and data modeling in the Cassandra NoSQL database are different from those in a traditional relational database.
Cassandra NoSQL数据库中的数据分布和数据建模与传统关系型数据库中的不同。
In this article, we’ll learn how a partition key, composite key, and clustering key form a primary key. We’ll also see how they differ. As a result, we’ll touch upon the data distribution architecture and data modeling topics in Cassandra.
在这篇文章中,我们将学习分区键、复合键和集群键如何形成主键。我们还将看到它们有什么不同。因此,我们将触及Cassandra的数据分布架构和数据建模主题。
2. Apache Cassandra Architecture
2.Apache Cassandra架构
Apache Cassandra is an open-source NoSQL distributed database built for high availability and linear scalability without compromising performance.
Apache Cassandra是一个开源的NoSQL分布式数据库,在不影响性能的情况下为高可用性和线性可扩展性而构建。
Here is the high-level Cassandra architecture diagram:
以下是高级别的Cassandra架构图。
In Cassandra, the data is distributed across a cluster. Additionally, a cluster may consist of a ring of nodes arranged in racks installed in data centers across geographical regions.
在Cassandra中,数据被分布在一个集群中。此外,一个集群可能由环形节点组成,这些节点被安排在安装在数据中心的机架上,跨越地理区域。
At a more granular level, virtual nodes known as vnodes assign the data ownership to a physical machine. Vnodes make it possible to allow each node to own multiple small partition ranges by using a technique called consistent hashing to distribute the data.
在更精细的层面上,被称为vnodes的虚拟节点将数据所有权分配给一台物理机。Vnodes通过使用一种称为一致散列的技术来分配数据,使得每个节点可以拥有多个小型分区范围。
A partitioner is a function that hashes the partition key to generate a token. This token value represents a row and is used to identify the partition range it belongs to in a node.
分区器是一个函数,它对分区键进行哈希处理以生成一个标记。这个令牌值代表一个行,用于识别它在一个节点中属于的分区范围。
However, a Cassandra client sees the cluster as a unified whole database and communicates with it using a Cassandra driver library.
然而,Cassandra客户端将集群视为一个统一的整体数据库,并使用Cassandra驱动库与它进行通信。
3. Cassandra Data Modeling
3.卡桑德拉数据建模
Generally, data modeling is a process of analyzing the application requirements, identifying the entities and their relationships, organizing the data, and so on. In relational data modeling, the queries are often an afterthought in the whole data modeling process.
一般来说,数据建模是一个分析应用需求、识别实体及其关系、组织数据等的过程。在关系型数据建模中,查询往往是整个数据建模过程中的事后想法。
However, in Cassandra, the data access queries drive the data modeling. The queries are, in turn, driven by the application workflows.
然而,在 Cassandra 中,数据访问查询驱动数据建模。而这些查询又是由应用程序的工作流程驱动的。
Additionally, there are no table-joins in the Cassandra data models, which implies that all desired data in a query must come from a single table. As a result, the data in a table is in a denormalized format.
此外,Cassandra数据模型中没有表连接,这意味着查询中所有需要的数据必须来自一个表。因此,表中的数据是以非规范化的格式出现的。
Next, in the logical data modeling step, we specify the actual database schema by defining keyspaces, tables, and even table columns. Then, in the physical data modeling step, we use the Cassandra Query Language (CQL) to create physical keyspaces — tables with all data types in a cluster.
接下来,在逻辑数据建模步骤中,我们通过定义关键空间、表,甚至表列来指定实际的数据库模式。然后,在物理数据建模步骤中,我们使用Cassandra查询语言(CQL)来创建物理键位–集群中所有数据类型的表。
4. Primary Key
4.主键
The way primary keys work in Cassandra is an important concept to grasp.
Cassandra中主键的工作方式是一个需要掌握的重要概念。
A primary key in Cassandra consists of one or more partition keys and zero or more clustering key components. The order of these components always puts the partition key first and then the clustering key.
Cassandra中的主键由一个或多个分区键和零个或多个聚类键组成。这些组件的顺序总是把分区键放在第一位,然后是聚类键。
Apart from making data unique, the partition key component of a primary key plays an additional significant role in the placement of the data. As a result, it improves the performance of reads and writes of data spread across multiple nodes in a cluster.
除了使数据独一无二之外,主键的分区键组件在数据的放置方面还发挥了额外的重要作用。因此,它提高了分布在集群中多个节点的数据的读写性能。
Now, let’s look at each of these components of a primary key.
现在,让我们来看看主键的每一个组成部分。
4.1. Partition Key
4.1.分区钥匙
The primary goal of a partition key is to distribute the data evenly across a cluster and query the data efficiently.
分区键的主要目标是将数据均匀地分布在一个集群中,并有效地查询数据。
A partition key is for data placement apart from uniquely identifying the data and is always the first value in the primary key definition.
分区键除了唯一标识数据外,还用于数据放置,并且总是主键定义中的第一个值。
Let’s try to understand using an example — a simple table containing application logs with one primary key:
让我们试着用一个例子来理解–一个包含应用日志的简单表,有一个主键。
CREATE TABLE application_logs (
id INT,
app_name VARCHAR,
hostname VARCHAR,
log_datetime TIMESTAMP,
env VARCHAR,
log_level VARCHAR,
log_message TEXT,
PRIMARY KEY (app_name)
);
Here are some sample data in the above table:
以下是上表中的一些样本数据。
As we learned earlier, Cassandra uses a consistent hashing technique to generate the hash value of the partition key (app_name) and assign the row data to a partition range inside a node.
正如我们之前学到的,Cassandra使用一致的散列技术来生成分区键(app_name)的散列值,并将行数据分配给节点内的分区范围。
Let’s look at possible data storage:
让我们来看看可能的数据存储。
The above diagram is a possible scenario where the hash values of app1, app2, and app3 resulted in each row being stored in three different nodes — Node1, Node2, and Node3, respectively.
上图是一个可能的场景,app1、app2和app3的哈希值导致每一行被存储在三个不同的节点–Node1、Node2和Node3。
All app1 logs go to Node1, app2 logs go to Node2, and app3 logs go to Node3.
所有app1日志都会转到Node1,app2日志转到Node2,app3日志转到Node3。
A data fetch query without a partition key in the where clause results in an inefficient full cluster scan.
在where子句中没有分区键的数据获取查询会导致低效的全集群扫描。
On the other hand, with a partition key in where clause, Cassandra uses the consistent hashing technique to identify the exact node and the exact partition range within a node in the cluster. As a result, the fetch data query is fast and efficient:
另一方面,对于where子句中的分区键,Cassandra使用一致性散列技术来识别集群中的确切节点和节点内的确切分区范围。因此,获取数据的查询是快速和高效的。
select * application_logs where app_name = 'app1';
4.2. Composite Partition Key
4.2 复合分区钥匙
If we need to combine more than one column value to form a single partition key, we use a composite partition key.
如果我们需要结合一个以上的列值来形成一个单一的分区键,我们使用复合分区键。
Here again, the goal of the composite partition key is for the data placement, in addition to uniquely identifying the data. As a result, the storage and retrieval of data become efficient.
在这里,复合分区密钥的目标也是为了数据的放置,除了唯一地识别数据之外。因此,数据的存储和检索变得高效。
Here’s an example of the table definition that combines the app_name and env columns to form a composite partition key:
下面是一个表定义的例子,它结合了app_name和env列,形成一个复合分区键。
CREATE TABLE application_logs (
id INT,
app_name VARCHAR,
hostname VARCHAR,
log_datetime TIMESTAMP,
env VARCHAR,
log_level VARCHAR,
log_message TEXT,
PRIMARY KEY ((app_name, env))
);
The important thing to note in the above definition is the inner parenthesis around app_name and env primary key definition. This inner parenthesis specifies that app_name and env are part of a partition key and are not clustering keys.
在上述定义中需要注意的是app_name和env主键定义周围的内括号。这个内括号指定app_name和env是分区键的一部分,不是集群键。
If we drop the inner parenthesis and have only a single parenthesis, then the app_name becomes the partition key, and env becomes the clustering key component.
如果我们去掉内部的小括号,只有一个小括号,那么app_name就变成了分区键,而env就变成了聚类键组件。
Here’s the sample data for the above table:
以下是上表的样本数据。
Let’s look at the possible data distribution of the above sample data. Please note: Cassandra generates the hash value for the app_name and env column combination:
让我们看看上述样本数据的可能数据分布。请注意:Cassandra为app_name和env列组合生成了哈希值。
As we can see above, the possible scenario where the hash value of app1:prod, app1:dev, app1:qa resulted in these three rows being stored in three separate nodes — Node1, Node2, and Node3, respectively.
正如我们在上面看到的,可能的情况是,app1:prod, app1:dev, app1:qa的哈希值导致这三条记录分别存储在三个独立的节点中–Node1, Node2, 和Node3。
All app1 logs from the prod environment go to Node1, while app1 logs from the dev environment go to Node2, and app1 logs from the qa environment go to Node3.
所有来自prod环境的app1日志都去往Node1,而来自dev环境的app1日志去往Node2,来自qa环境的app1日志去往Node3。
Most importantly, to efficiently retrieve data, the where clause in fetch query must contain all the composite partition keys in the same order as specified in the primary key definition:
最重要的是,为了有效地检索数据,fetch查询中的where子句必须包含所有复合分区键,其顺序与主键定义中指定的顺序相同。
select * application_logs where app_name = 'app1' and env = 'prod';
4.3. Clustering Key
4.3.聚类的关键
As we’ve mentioned above, partitioning is the process of identifying the partition range within a node the data is placed into. In contrast, clustering is a storage engine process of sorting the data within a partition and is based on the columns defined as the clustering keys.
正如我们上面提到的,分区是确定数据被放入节点内的分区范围的过程。相比之下,聚类是一个存储引擎对分区内的数据进行排序的过程,它是基于定义为聚类键的列。
Moreover, identification of the clustering key columns needs to be done upfront — that’s because our selection of clustering key columns depends on how we want to use the data in our application.
此外,对聚类关键列的识别需要在前期完成–这是因为我们对聚类关键列的选择取决于我们想在应用中如何使用数据。
All the data within a partition is stored in continuous storage, sorted by clustering key columns. As a result, the retrieval of the desired sorted data is very efficient.
一个分区内的所有数据都被存储在连续的存储器中,按聚类的关键列进行排序。因此,检索所需的排序数据是非常有效的。
Let’s look at an example table definition that has the clustering keys along with the composite partition keys:
让我们看看一个表定义的例子,它有聚类键和复合分区键。
CREATE TABLE application_logs (
id INT,
app_name VARCHAR,
hostname VARCHAR,
log_datetime TIMESTAMP,
env VARCHAR,
log_level VARCHAR,
log_message TEXT,
PRIMARY KEY ((app_name, env), hostname, log_datetime)
);
And let’s see some sample data:
让我们来看看一些样本数据。
As we can see in the above table definition, we’ve included the hostname and the log_datetime as clustering key columns. Assuming all the logs from app1 and prod environment are stored in Node1, the Cassandra storage engine lexically sorts those logs by the hostname and the log_datetime within the partition.
正如我们在上面的表定义中看到的,我们把hostname和log_datetime作为集群的关键列。假设所有来自app1和prod环境的日志都存储在Node1中,Cassandra存储引擎根据hostname和log_datetime在该分区中对这些日志进行词法排序。
By default, the Cassandra storage engine sorts the data in ascending order of clustering key columns, but we can control the clustering columns’ sort order by using WITH CLUSTERING ORDER BY clause in the table definition:
默认情况下,Cassandra存储引擎会按照聚类关键列的升序对数据进行排序,但我们可以通过在表定义中使用WITH CLUSTERING ORDER BY 条款来控制聚类列的排序顺序。
CREATE TABLE application_logs (
id INT,
app_name VARCHAR,
hostname VARCHAR,
log_datetime TIMESTAMP,
env VARCHAR,
log_level VARCHAR,
log_message TEXT,
PRIMARY KEY ((app_name,env), hostname, log_datetime)
)
WITH CLUSTERING ORDER BY (hostname ASC, log_datetime DESC);
Per the above definition, within a partition, the Cassandra storage engine will store all logs in the lexical ascending order of hostname, but in descending order of log_datetime within each hostname group.
根据上述定义,在一个分区内,Cassandra存储引擎将按照hostname的词法升序来存储所有日志,但在每个hostname组内则按照log_datetime的降序来存储。
Now, let’s look at an example of the data fetch query with clustering columns in the where clause:
现在,让我们看看一个在where子句中带有聚类列的数据获取查询的例子。
select * application_logs
where
app_name = 'app1' and env = 'prod'
and hostname = 'host1' and log_datetime > '2021-08-13T00:00:00';
What’s important to note here is that the where clause should contain the columns in the same order as defined in the primary key clause.
这里需要注意的是,where子句应该包含与主键子句中定义的相同顺序的列。
5. Conclusion
5.总结
In this article, we learned that Cassandra uses a partition key or a composite partition key to determine the placement of the data in a cluster. The clustering key provides the sort order of the data stored within a partition. All of these keys also uniquely identify the data.
在这篇文章中,我们了解到,Cassandra使用分区键或复合分区键来确定数据在集群中的位置。集群键提供了存储在一个分区中的数据的排序顺序。所有这些键也都能唯一地识别数据。
We also touched upon the Cassandra architecture and data modeling topics.
我们还涉及到了Cassandra架构和数据建模的话题。
For more information on Cassandra, visit the DataStax and Apache Cassandra documentation.
有关 Cassandra 的更多信息,请访问 DataStax 和 Apache Cassandra 文档。