Apache Cassandra 快速入門指南

  • 2019 年 10 月 30 日
  • 筆記

我們在這篇文章簡單介紹了 Apache Cassandra 是什麼,以及有什麼值得關注的特性。本文將簡單介紹 Apache Cassandra 的安裝以及簡單使用,可以幫助大家快速了解 Apache Cassandra。

我們到 Apache Cassandra 的官方網站下載最新版本的 Cassandra,在本文寫作時最新版本的 Cassandra 為 3.11.4。Apache Cassandra 可以在 Linux、Unix、Mac OS 以及 Windows 上進行安裝,為了簡便起見,本文以 CentOS 為例進行介紹。

下載、安裝並啟動 Cassandra

因為本文只是簡單介紹 Apache Cassandra 的使用,所以本文僅安裝單機版的 Cassandra,在生產環境下應該部署成分散式模式。可以使用下面的命令下載和解壓相關的壓縮文件:

$ wget http://mirror.bit.edu.cn/apache/cassandra/3.11.4/apache-cassandra-3.11.4-bin.tar.gz  $ tar -zxf apache-cassandra-3.11.4-bin.tar.gz  $ cd apache-cassandra-3.11.4 

在 apache-cassandra-3.11.4 目錄下有很多文件:

[[email protected] apache-cassandra-3.11.4]# ll  total 528  drwxr-xr-x 2 iteblog iteblog   4096 Apr  2 21:12 bin  -rw-r--r-- 1 iteblog iteblog   4832 Feb  3 06:09 CASSANDRA-14092.txt  -rw-r--r-- 1 iteblog iteblog 366951 Feb  3 06:09 CHANGES.txt  drwxr-xr-x 3 iteblog iteblog   4096 Apr  2 21:12 conf  drwxr-xr-x 4 iteblog iteblog   4096 Apr  2 21:12 doc  drwxr-xr-x 2 iteblog iteblog   4096 Apr  2 21:12 interface  drwxr-xr-x 3 iteblog iteblog   4096 Apr  2 21:12 javadoc  drwxr-xr-x 4 iteblog iteblog   4096 Apr  2 21:12 lib  -rw-r--r-- 1 iteblog iteblog  11609 Feb  3 06:09 LICENSE.txt  -rw-r--r-- 1 iteblog iteblog 112586 Feb  3 06:09 NEWS.txt  -rw-r--r-- 1 iteblog iteblog   2811 Feb  3 06:09 NOTICE.txt  drwxr-xr-x 3 iteblog iteblog   4096 Apr  2 21:12 pylib  drwxr-xr-x 4 iteblog iteblog   4096 Apr  2 21:12 tools

各個文件或目錄介紹如下:

  • bin:這個目錄下包含了啟動 Cassandra 以及客戶端相關操作的可執行文件,包括 query language shell(cqlsh)以及命令行介面(CLI)等客戶端。同時還包含運行 nodetool 的相關腳本,操作 SSTables 的工具等等。
  • conf:這個目錄下面包含了 Cassandra 的配置文件。必須包含的配置文件包括:assandra.yaml 以及 logback.xml,這兩個文件分別是運行 Cassandra 必須包含的配置文件以及日誌相關配置文件。同時還包含 Cassandra 網路拓撲配置文件等。
  • doc:這個目錄包含 CQL 相關的 html 文檔。
  • interface:這個文件夾下面只包含一個名為 cassandra.thrift 的文件。這個文件定義了基於 Thrift 語法的 RPC API,這個 Thrift 主要用於在 Java, C++, PHP, Ruby, Python, Perl, 以及 C# 等語言中創建相關客戶端,但是在 CQL 出現之後,Thrift API 在 Cassandra 3.2 版本開始標記為 deprecated,並且會在 Cassandra 4.0 版本刪除。
  • javadoc:這個文件夾包含使用 JavaDoc 工具生成的 html 文檔。
  • lib:這個目錄包含 Cassandra 運行時需要的所有外部庫。
  • pylib:這個目錄包含 cqlsh 運行時需要使用的 Python 庫。
  • tools:這個目錄包含用於維護 Cassandra 節點的相關工具。
  • NEWS.txt:這個文件包含當前及之前版本的 release notes 相關資訊。
  • CHANGES.txt:這個文件主要包含一些 bug fixes 資訊。

啟動 Cassandra

上面已經簡單介紹了 Cassandra 發行包裡面的一些文件和目錄用途。因為我們主要簡單介紹 Cassandra 的使用,所以我們使用默認的配置。下面我們來啟動 Cassandra 服務,具體如下:

[[email protected] apache-cassandra-3.11.4]# bin/cassandra

運行上面命令會在命令行裡面輸出一堆的日誌,但是我們如何判斷 cassandra 服務已經啟動了呢?答案是使用 nodetool 工具,如下:

[[email protected] apache-cassandra-3.11.4]# bin/nodetool status  Datacenter: datacenter1  =======================  Status=Up/Down  |/ State=Normal/Leaving/Joining/Moving  --  Address    Load       Tokens       Owns (effective)  Host ID                               Rack  UN  127.0.0.1  160.88 KiB  256          100.0%            49f4470f-396b-4d50-bcd6-3da2d9370167  rack1

如果我們看到上面的資訊,那麼我們的測試服務已經正常啟動了。而且會在 apache-cassandra-3.11.4 目錄下生成 data 和 logs 兩個目錄。

使用 CQL Shell

上面我們已經啟動了 Cassandra 服務,我們可以使用 CQL Shell 來進行一些操作。從名字就可以看出,CQL(Cassandra Query Language) 其實和我們熟悉的 SQL 很類似,我們可以通過它使用類似 SQL 的語言來和 Cassandra 進行交互。需要注意的是,CQL 和 SQL 是不兼容的,CQL 缺少 SQL 的一些關鍵功能,比如 JOIN 等,這個在 Cassandra 下不能實現;同時,CQL 也不是 SQL 的子集。為了使用 CQL ,可以使用下面命令:

[[email protected] apache-cassandra-3.11.4]# bin/cqlsh  Connected to Test Cluster at 127.0.0.1:9042.  [cqlsh 5.0.1 | Cassandra 3.11.4 | CQL spec 3.4.4 | Native protocol v4]  Use HELP for help.  cqlsh>

在啟動 cqlsh 的時候我們並沒有指定需要連接的節點以及埠,這種情況下 cqlsh 會自動探測本機及相關埠,因為我們在前面已經啟動了 Cassandra 服務,所以 cqlsh 可以正確連接到這個集群。從上面的命令可以看出 cqlsh 連接到名為 Test Cluster 的集群,這是由 conf/cassandra.yaml 文件裡面的 cluster_name 參數決定的,默認值為 Test Cluster。

當然,我們也可以在啟動 cqlsh 的時候指定節點和相應的埠,如下:

[[email protected] apache-cassandra-3.11.4]# bin/cqlsh localhost 9042

上面的命令執行效果和不指定一樣。我們也可以將節點和埠相關的資訊保存到環境變數

和CQLSHHOST和CQLSH_PORT 裡面,這個在我們需要經常連接到特定節點的情況下非常有用。更多關於 cqlsh 命令支援的參數可以使用 bin/cqlsh -help。

基本的 cqlsh 命令

cqlsh 支援很多操作 Cassandra 的基本命令,我們可以在 cqlsh 裡面使用 HELP 或 ? 命令查看所有支援的命令:

cqlsh> HELP    Documented shell commands:  ===========================  CAPTURE  CLS          COPY  DESCRIBE  EXPAND  LOGIN   SERIAL  SOURCE   UNICODE  CLEAR    CONSISTENCY  DESC  EXIT      HELP    PAGING  SHOW    TRACING    CQL help topics:  ================  AGGREGATES               CREATE_KEYSPACE           DROP_TRIGGER      TEXT  ALTER_KEYSPACE           CREATE_MATERIALIZED_VIEW  DROP_TYPE         TIME  ALTER_MATERIALIZED_VIEW  CREATE_ROLE               DROP_USER         TIMESTAMP  ALTER_TABLE              CREATE_TABLE              FUNCTIONS         TRUNCATE  ALTER_TYPE               CREATE_TRIGGER            GRANT             TYPES  ALTER_USER               CREATE_TYPE               INSERT            UPDATE  APPLY                    CREATE_USER               INSERT_JSON       USE  ASCII                    DATE                      INT               UUID  BATCH                    DELETE                    JSON  BEGIN                    DROP_AGGREGATE            KEYWORDS  BLOB                     DROP_COLUMNFAMILY         LIST_PERMISSIONS  BOOLEAN                  DROP_FUNCTION             LIST_ROLES  COUNTER                  DROP_INDEX                LIST_USERS  CREATE_AGGREGATE         DROP_KEYSPACE             PERMISSIONS  CREATE_COLUMNFAMILY      DROP_MATERIALIZED_VIEW    REVOKE  CREATE_FUNCTION          DROP_ROLE                 SELECT  CREATE_INDEX             DROP_TABLE                SELECT_JSON

如果需要查看特定命令的幫助,可以使用 HELP 。需要注意的是,很多 cqlsh 命令並不接收相關的參數,當我們使用這些命令時,其輸出為當前的設置,比如 CONSISTENCY, EXPAND 和 PAGING 命令,如下:

cqlsh> CONSISTENCY  Current consistency level is ONE.  cqlsh> EXPAND  Expanded output is currently disabled. Use EXPAND ON to enable.  cqlsh> PAGING  Query paging is currently enabled. Use PAGING OFF to disable  Page size: 100

在 cqlsh 裡面查看環境變數

我們可以使用 DESCRIBE 命令,來查看一些集群的一些環境變數的值。下面命令查看當前集群的情況

cqlsh> DESCRIBE CLUSTER;    Cluster: Test Cluster  Partitioner: Murmur3Partitioner

DESCRIBE CLUSTER 顯示了集群的名字以及採用的 Partitioner ,Cassandra 1.2 版本開始默認為 Murmur3Partitioner,其他可選的 Partitioner 有 RandomPartitioner(Cassandra 1.2 版本之前默認的 Partitioner)、OrderPreservingPartitioner 以及 ByteOrderedPartitioner 等。

如果我們需要查看集群裡面可用的 keyspaces,可以使用下面命令:

cqlsh> DESCRIBE KEYSPACES;    system_traces  system_schema  system_auth  system  system_distributed

上面命令將系統自帶的 keyspaces 都顯示出來了,如果我們自己創建了 keyspaces,也會在這裡面顯示。

可以使用下面命令查看 cqlsh、Cassandra 以及 protocol 的版本:

cqlsh> SHOW VERSION;  [cqlsh 5.0.1 | Cassandra 3.11.4 | CQL spec 3.4.4 | Native protocol v4]

通過 cqlsh 創建 keyspace

Cassandra 裡面的 keyspace 和關係型資料庫裡面的 database 概念類似的,一個 keyspace 可以包含一個或多個 tables 或 column families。當我們啟動 cqlsh 時沒有指定 keyspace,那麼命令提示符為 cqlsh>,我們可以使用 CREATE KEYSPACE 命令來創建 keyspace,具體如下:

cqlsh> CREATE KEYSPACE iteblog_keyspace WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1};  cqlsh>

上面命令創建了名為 iteblog_keyspace 的 keyspace;並且採用 SimpleStrategy 進行副本複製,因為我們這個測試集群只有單個節點,所以這裡設置的副本因子(replication factor)為 1。如果是生產環境,千萬別把副本因子設置為 1,比較常見的副本因子為 3。其他可選的副本複製策略出了 SimpleStrategy 還有 NetworkTopologyStrategy 和 OldNetworkTopologyStrategy,具體什麼含義這裡還不深入介紹,後面會起單獨一篇文章進行詳細介紹。

創建完 keyspace 之後,我們可以使用 DESCRIBE KEYSPACE 命令來查看這個 keyspace:

cqlsh> DESCRIBE KEYSPACE  iteblog_keyspace;    CREATE KEYSPACE iteblog_keyspace WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'}  AND durable_writes = true;

現在我們可以使用 USE 命令來切換到這個 keyspace :

cqlsh> USE iteblog_keyspace;  cqlsh:iteblog_keyspace>

從上面的輸出可以看出,keyspace 已經切換到 iteblog_keyspace 了。

通過 cqlsh 創建表

接下來,我們通過 cqlsh 來創建一張表:

cqlsh> use iteblog_keyspace;  cqlsh:iteblog_keyspace> CREATE TABLE iteblog_user (first_name text , last_name text, PRIMARY KEY (first_name)) ;

通過上面的命令,我們在 iteblog_keyspace 下面創建了一張名為 iteblog_user 的表。其中包含了 first_name 和 last_name 兩個欄位,類型都是 text,並且 first_name 是這張表的 PRIMARY KEY。當然,我們也可以通過下面命令在 iteblog_keyspace 裡面建表:

cqlsh> CREATE TABLE iteblog_keyspace.iteblog_user(first_name text , last_name text, PRIMARY KEY (first_name)) ;

效果和上面一樣。我們可以使用 DESCRIBE TABLE 命令查看建表語句:

cqlsh:iteblog_keyspace> DESCRIBE TABLE iteblog_user;    CREATE TABLE iteblog_keyspace.iteblog_user (      first_name text PRIMARY KEY,      last_name text  ) WITH bloom_filter_fp_chance = 0.01      AND caching = {'keys': 'ALL', 'rows_per_partition': 'NONE'}      AND comment = ''      AND compaction = {'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy', 'max_threshold': '32', 'min_threshold': '4'}      AND compression = {'chunk_length_in_kb': '64', 'class': 'org.apache.cassandra.io.compress.LZ4Compressor'}      AND crc_check_chance = 1.0      AND dclocal_read_repair_chance = 0.1      AND default_time_to_live = 0      AND gc_grace_seconds = 864000      AND max_index_interval = 2048      AND memtable_flush_period_in_ms = 0      AND min_index_interval = 128      AND read_repair_chance = 0.0      AND speculative_retry = '99PERCENTILE';    cqlsh:iteblog_keyspace>

DESCRIBE TABLE 命令將建表語句以格式化的形式顯示出來。除了我們制定的設置,還包含了許多默認的設置,這裡我們先不糾結這些設置的含義。

通過 cqlsh 往表裡面讀寫數據

到現在,我們已經創建好 keyspace 和 table 了,我們可以往表裡面插入一些數據,看下一切是不是正常。

cqlsh:iteblog_keyspace> INSERT INTO iteblog_user (first_name, last_name) VALUES ('iteblog', 'Hadoop');  cqlsh:iteblog_keyspace> INSERT INTO iteblog_user (first_name, last_name) VALUES ('Zhang', 'San');  cqlsh:iteblog_keyspace> INSERT INTO iteblog_user (first_name) VALUES ('Wu');

上面語句我們往 iteblog_user 表裡面插入三條數據,其中最後一條數據只指定了 key,last_name 沒有值。現在我們可以使用 SELECT COUNT 語句查看上面的數據是否插入成功

cqlsh:iteblog_keyspace> SELECT COUNT(*) FROM iteblog_user;     count  -------       3    (1 rows)    Warnings :  Aggregation query used without partition key

可以看出 iteblog_user 表裡面已經有3條數據了。我們可以使用下面命令將這條數據查詢出來:

cqlsh:iteblog_keyspace> SELECT * FROM iteblog_user;     first_name | last_name  ------------+-----------      iteblog |    Hadoop           Wu |      null        Zhang |       San    (3 rows)  cqlsh:iteblog_keyspace> SELECT * FROM iteblog_user WHERE first_name='iteblog';     first_name | last_name  ------------+-----------      iteblog |    Hadoop    (1 rows)  cqlsh:iteblog_keyspace>

可以看出,first_name 為 Wu 對應的 last_name 沒數據直接顯示 null 了,在 Cassandra 裡面的這個代表對應的列沒有數據,在底層存儲是不佔用空間的,而在常見的關係型資料庫裡面是佔一定空間的。

我們可以使用 DELETE 命令刪除一些列,比如我們刪除 last_name 列,

cqlsh:iteblog_keyspace> DELETE last_name FROM iteblog_user WHERE first_name='iteblog';  cqlsh:iteblog_keyspace> SELECT * FROM iteblog_user WHERE first_name='iteblog';     first_name | last_name  ------------+-----------      iteblog |      null    (1 rows)  cqlsh:iteblog_keyspace>

可以看出 last_name 列已經成功被刪除了。

我們也可以刪除一整行數據,如下:

cqlsh:iteblog_keyspace> DELETE FROM iteblog_user WHERE first_name='iteblog';  cqlsh:iteblog_keyspace> SELECT * FROM iteblog_user WHERE first_name='iteblog';     first_name | last_name  ------------+-----------    (0 rows)  cqlsh:iteblog_keyspace>

可以看到 key 為 iteblog 的數據已經成功被刪除了。

insert/update 相當於 upsert

如果我們插入數據對應的 key 在 Cassandra 已經存在了,這時候 Cassandra 並不會在原來數據位置上修改數據,而是會新寫入一份數據,舊的數據會被 Cassandra 刪除。

cqlsh:iteblog_keyspace> INSERT INTO iteblog_user (first_name, last_name) VALUES ('Wu', 'Shi');  cqlsh:iteblog_keyspace> SELECT * FROM iteblog_user;     first_name | last_name  ------------+-----------           Wu |       Shi        Zhang |       San    (2 rows)

可以看見,key 為 Wu 的數據對應的 last_name 已經有值了。

如果我們使用 UPDATE 命令往表裡面更新不存在的數據會發生什麼呢?答案是會插入新的數據。

cqlsh:iteblog_keyspace> SELECT * FROM iteblog_user;     first_name | last_name  ------------+-----------           Wu |       Shi        Zhang |       San    (2 rows)  cqlsh:iteblog_keyspace> UPDATE iteblog_user SET last_name = 'Si' WHERE first_name = 'Li';  cqlsh:iteblog_keyspace> SELECT * FROM iteblog_user;     first_name | last_name  ------------+-----------           Wu |       Shi        Zhang |       San           Li |        Si    (3 rows)  cqlsh:iteblog_keyspace>

可見,key 為 Li 的數據被插入到表中了,更新之前不存在。

清空或刪除表

如果我們確實想清空一張表,我們也可以使用 TRUNCATE 命令;使用 DROP TABLE 命令可以刪除一張表。

cqlsh:iteblog_keyspace> TRUNCATE iteblog_user;  cqlsh:iteblog_keyspace> DROP TABLE iteblog_user;

到目前為止,我們已經學會了 cqlsh 的一些簡單的命令。