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 的一些簡單的命令。