Cassandra研究報告
1基本安裝
1.1在基于RHEL的系統中安裝Cassandra
1.1.1必要條件
? YUM包管理器
? Root或sudo權限
? JRE6或者JRE7
? JNA(Java native Access)(生產環境需要)
1.1.2步驟
? 安裝配置JRE(略)
? 添加軟件包倉庫到YUM的軟件庫
將以下內容添加進/etc/yum.repos.d/datastax.repo文件即可:
[datastax]
name = DataStax Repo for ApacheCassandra
baseurl =http://rpm.datastax.com/community
enabled = 1
gpgcheck = 0
? 安裝2.0版最新的軟件包
$ sudo yuminstall dsc20
? 安裝JNA
$ sudo yuminstall jna
經過上述步驟即安裝好了Cassandra,隨后便可對其進行配置。以此方式安裝的Cassandra會創建一個名為cassandra的用戶,cassandra以此用戶啟動服務。
1.2在任意基于Linux的系統中安裝Cassandra
1.2.1必要條件
? JRE6或者JRE7
? JNA(Java native Access) (生產環境需要)
1.2.2步驟
? 安裝配置JRE(略)
? 下載Cassandra二進制 tarball
由http://planetcassandra.org/Download/StartDownload頁面手工下載對應版本的Cassandra,或者通過curl -OLhttp://downloads.datastax.com/community/dsc.tar.gz命令自動下載最新的DataStaxCommunity,也可由http://cassandra.apache.org/download/頁面手工下載對應版本。
? 解壓tarball
tar –xzvf dsc-cassandra-2.0.0-bin.tar.gz
根據下載的版本也可能是:tar –xzvf apache-cassandra-2.0.0-bin.tar.gz
? 安裝配置JNA
2 下載jna.jar(https://github.com/twall/jna/ )。
2 將下載的jna.jar添加進Cassandra安裝目錄的lib目錄下或將其添加進CLASSPATH環境變量中
2 在/etc/security/limits.conf文件中加入如下行:
$USER soft memlock unlimited
$USER hard memlock unlimited
其中$USER為運行cassandra的用戶
? 創建數據目錄和日志目錄并指定給用于運行cassandra服務的具有相應讀寫權限的用戶
$ sudo mkdir/var/lib/cassandra
$ sudo mkdir/var/log/cassandra
$ sudo chown-R $USER: $GROUP /var/lib/cassandra
$ sudo chown-R $USER: $GROUP /var/log/Cassandra
Cassandra配置文件中默認使用上述目錄分別作為數據目錄和日志目錄,可創建不同的目錄,賦予對應的權限,并在配置文件中重新指定以改變默認行為。
至此已安裝好了Cassandra,隨后便可對其進行配置。
1.3在其他平臺安裝Cassandra(略)
1.5通過源碼構建Cassandra(略)
2簡單配置
Cassandra的主配置文件為cassandra.yaml,其位置隨Cassandra安裝方式不同而不同。
? 對于CassandraPackage安裝:/etc/cassandra/conf
? 對于CassandraBinary安裝:<install_location>/conf
? 對于DataStaxEnterprise Packaged安裝:/etc/dse/cassandra
? 對于DataStaxEnterpriseBinary安裝:<install_location>/resources/cassandra/conf
配置文件中的配置參數被分為如下幾個組
? Initialization properties:控制集群內的節點如何配置,包括節點間通訊,數據分區及復制布置。
? Global row and key caches properties:用于緩存表的參數的配置參數。
? Performance tuning properties:調整性能和系統資源的利用,包括內存、磁盤I/O、CPU、讀和寫。
? Binary and RPC protocol timeout properties:用于二進制協議的超時設置。
? Remote procedure call tuning(RPC)properties:用于配置和調整RPCs(客戶端連接)
? Fault detection properties:用于處理運行情況較差或者失敗的節點。
? Automatic backup properties:用于自動化備份。
? Security properties:用于服務器端和客戶端的安全設置
每個組包都含若干具體的參數(具體內容可參考:http://www.datastax.com/documentation/cassandra/1.2/webhelp/index.html#cassandra/configuration/configCassandra_yaml_r.html)
例如,對于新安裝的Cassandra可能會修改配置文件中的下面幾個參數
? data_file_directories:數據目錄,對于包方式(如deb或rpm)安裝的Cassandra,該目錄會在安裝過程中自動創建并具有正確的權限,默認位置為/var/lib/cassandra/data。
? commitlog_directory:commit log目錄,對于包方式安裝的Cassandra,該目錄會在安裝過程中自動創建并具有正確的權限,默認位置為/var/lib/cassandra/commitlog。
? saved_caches_directory:保存的緩存目錄,對于包方式安裝的Cassandra,該目錄會在安裝過程中自動創建并具有正確的權限,默認位置為/var/lib/cassandra/saved_caches。
如果以二進制方式或源碼方式安裝Cassandra需自行創建相應目錄,賦予正確的權限。又或者不想使用默認的位置,也可以自行創建新的目錄,賦予正確的權限,并在配置文件中指定。比如:
data_file_directories:/data/cassandra/data
commitlog_directory:/data/cassandra/commitlog
saved_caches_directory:/data/cassandra/saved_caches
另外,對于包方式安 裝的Cassandra,還會在安裝過程中自動創建/var/log/cassandra目錄并賦予正確的權限。默認情況下Cassandra將其日志寫 進該目錄的system.log文件中。可通過修改log4j-server.properies文件(與cassandra.yaml位于同一目錄)中 的log4j.appender.R.File來改變默認行為,比如:log4j.appender.R.File=/data/cassandra /system.log
還可能要修改JVM級別的參數,該部分的參數可在cassandra-env.sh文件(與cassandra.yaml位于同一目錄)中設置。
3啟動及簡單使用
3.1啟動Cassandra
對于二進制包安裝方式
? 執行bin/cassandra–f,前臺啟動cassandra,cassandra會將日志輸出到標準輸出中。若沒在輸出中看到“error”、 “fatal”或者類似“java stack trace”的內容表明cassandra可正常工作。可通過“Control-C“停止casandra。
? 執行bin/cassandra,后臺啟動cassandra。
? 可通過kill或pkill命令停止cassandra
對于YUM安裝方式
? 執行sudoservice Cassandra start啟動cassandra
? 執行sudoservice Cassandra stop 停止cassandra
3.2使用cqlsh
執行bin/cqlsh,出現如下提示則表明連接成功(需python2.7):
Connected toTest Cluster at localhost:9160.
[cqlsh 4.0.0 |Cassandra 2.0.0 | CQL spec 3.1.0 | Thrift protocol 19.37.0]
Use HELP forhelp.
可在cqlsh命令提示符下輸入help或?獲得幫助,輸入exit或quit退出cqlsh,命令默認以“;”結束。
查看keyspace
DESCRIBEkeyspaces;
創建keyspace
CREATEKEYSPACE mykeyspace WITH REPLICATION = { 'class' : 'SimpleStrategy','replication_factor' : 2 };
切換keyspace
USE mykeyspace;
創建表
CREATE TABLEusers (
user_id int PRIMARY KEY,
fname text,
lname text
);
查看表
DESCRIBETABLES;
插入數據
INSERT INTOusers (user_id, fname, lname)
VALUES (1745, 'john', 'smith');
INSERT INTOusers (user_id, fname, lname)
VALUES (1744, 'john', 'doe');
INSERT INTOusers (user_id, fname, lname)
VALUES (1746, 'john', 'smith');
查詢數據
SELECT * FROMusers;
建立索引后使用WHERE從句查找
CREATE INDEXON users (lname);
SELECT * FROMusers WHERE lname = 'smith';
刪除表
DROP TABLEusers;
至此已經擁有了單節點的Cassandra,且能夠通過cqlsh連接至cassandra并使用CQL執行操作。下面對Cassandra作進一步介紹。
4搭建集群
4.1單數據中心集群
4.1.1前置工作
? 在每個節點上裝配Cassandra
? 為集群確定名稱
? 獲取每個節點的IP
? 確定用來做種子的節點(Cassandra通過種子節點來找到彼此并了解環的拓撲)
? 確定snitch(用于確定向/從哪個數據中心和網架寫入/讀取數據。有不同的類型可選,具體參考:http://www.datastax.com/documentation/cassandra/2.0/webhelp/cassandra/architecture/architectureSnitchesAbout_c.html)
4.1.2具體配置
1.假定使用以下已經安裝了Cassandra的節點配置集群(資源有限,這里只用兩臺機器來說明過程。真實環境下最好是有多臺機器,且一個集群中最好有一個以上的種子)
node0192.168.83.35 (seed)
node1192.168.83.37
2.假定節點所在機器有防火墻,注意開放Cassandra所使用的端口(相關端口可查http://www.datastax.com/documentation/cassandra/2.0/webhelp/cassandra/security/secureFireWall_r.html)
3.若Cassandra正運行則先關閉,后清除數據。
$ sudo servicecassandra stop
或者(根據安裝方式而不同)
$ ps auwx |grep cassandra
$ sudo kill <pid>
4.清除數據
$ sudo rm -rf/var/lib/cassandra/*
5.修改cassandra.yaml文件中的相應內容
cluster_name:'MyDemoCluster'
num_tokens:256
seed_provider:
- class_name:org.apache.cassandra.locator.SimpleSeedProvider
parameters:
- seeds: "192.168.83.35"
listen_address:192.168.83.35
rpc_address:0.0.0.0
endpoint_snitch:SimpleSnitch
若是建立全新的還不包含數據的集群則加上auto_bootstrap:false
6.剩余節點的配置與除了listen_address應當為自身IP外,其他配置與上述相同
7.先啟動逐個啟動seed節點,再逐個啟動剩余節點
$ sudo servicecassandra start
或者
$ cd<install_location>
$ bin/Cassandra
8.使用nodetoolstatus命令查看集群是否成功運行
4.2多數據中心集群
這里,數據中心指的就是一組節點,與復制組是同義詞。多數據中心集群中,數據可以在不同數據中心間自動、透明復制。
4.2.1前置工作
與單節點集群配置基本相同,不同的是還需要確定數據中心和網架的命名。
4.2.2具體配置
1.假定在以下已經安裝了Cassandra的節點配置集群
node0 192.168.83.35(seed1)
node1 192.168.83.36
node2 192.168.83.37
node3 192.180.83.35(seed2)
node4 192.180.83.36
node5 192.168.83.37
2.若如防火墻,則先開放相應端口(同上)
3.若Cassandra正運行則先關閉(同上)
4.清除數據(同上)
5.修改cassandra.yaml文件中的相應內容
…同上…
endpoint_snitch:PropertyFileSnitch
若是建立全新的還不包含數據的集群則加上auto_bootstrap:false
6.剩余節點的配置與除了listen_address應當為自身IP外,其他配置與上述相同
7.步驟5中指定 endpoint_snitch為PropertyFileSnitch所以要編輯對應的cassandra- topologies.properties配置文件(若endpoint_snitch指定為GossipingPropertyFileSnitch 則要編輯cassandra-rackdc.properties,指定為YamlFileNetworkTopologySnitch則要編輯 cassandra-topology.yaml)
# CassandraNode IP=Data Center:Rack
192.168.83.35=DC1:RAC1
192.168.83.36=DC2:RAC1
192.168.83.37=DC1:RAC1
192.180.83.35 =DC2:RAC1
192.180.83.36=DC1:RAC1
192.168.83.37=DC2:RAC1
之后還要為位置的節點設置一個默認的數據中心和網架名
# default forunknown nodes
default=DC1:RAC1
8.逐個啟動種子節點,之后逐個啟動剩余節點(同上)
9.驗證環是否成功啟動(同上)
5使用CQL
CQL:CassandraQuery Language
激活CQL:cqlsh、DataStaxJava Driver、Thrift方法set_cql_version、Python驅動中的connect()調用。
使用cqlsh
bin/cqlsh hostport –u username –p password
創建keyspace
keyspace為表命名空間,指明節點中數據如何復制,一般一個應用對應一個keyspace。cassandra中的復制控制以單個keyspace為基礎。
CREATEKEYSPACE demodb WITH REPLICATION = {'class' : 'SimpleStrategy','replication_factor': 3};
class指明復制策略,replication_factor指明復制的份數
使用keyspace
USE demodb;
更新keyspace
ALTER KEYSPACEdemodb WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 2};
ALTER KEYSPACEdemodb WITH REPLICATION ={'class' : 'NetworkTopologyStrategy', 'dc1' : 3, 'dc2': 2};
之后在每個受影響的節點執行nodetoolrepair demodb
創建表
use demodb
CREATE TABLEusers (
user_name varchar,
password varchar,
gender varchar,
session_token varchar,
state varchar,
birth_year bigint,
PRIMARY KEY (user_name));
使用復合primary key創建表
CREATE TABLEemp (
empID int,
deptID int,
first_name varchar,
last_name varchar,
PRIMARY KEY (empID, deptID));
插入數據
INSERT INTOemp (empID, deptID, first_name, last_name) VALUES (104, 15, 'jane', 'smith');
查詢表(以系統表為例)
system是 Cassandra的系統庫,當前含schema_keyspaces、local、peers、schema_columns和 schema_columnfamilies幾個表,分別包含keyspace信息,本地節點信息、集群節點信息、columns信息和 columnfamilies信息
use system
SELECT * from schema_keyspaces;獲取到當前節點中的eyspace
SELECT * FROMpeers獲取節點所在集群信息
提取并排序查詢結果
SELECT * FROMemp WHERE empID IN (103,104) ORDER BY deptID DESC;
使用keyspace限定符
經常使用USE keyspacename來切換keyspace可能不方便,可使用keyspace限定符指定表所屬的keyspace,如
SELECT * fromsystem.schema_keyspaces;
可在ALTER TABLEC、REATE TABLE、DELETE、INSERT、SELECT、TRUNCATE、UPDATE中使用
指定column的過期時間
INSERT INTOemp (empID, deptID, first_name, last_name) VALUES (105, 17, 'jane', 'smith')USING TTL 60;
其中USING TTL 60指明該條數據60秒后過期,屆時會被自動刪除。另外指定了TTL的數據columns會在compaction和repair操作中被自動刪除。指定TTL會有8字節額外開銷。
查詢過期時間
SELECT TTL(last_name)from emp;
更新過期時間
INSERT INTOemp (empID, deptID, first_name, last_name) VALUES (105, 17, 'miaomiao', 'han')USING TTL 3600;也即,以新的TTL重插一遍數據即可。(指定插入的整條數據的過期時間)
或者UPDATA emp USINGTTL 3600 SET last_name='han' where empid=105 and deptid=17; (指定set指明的數據的過期時間)
查詢寫入時間
SELECTWRITETIME(first_name) from emp;可查的該數據何時被插入。
添加columns
ALTER TABLEemp ADD address varchar;
更改column數據類型
ALTER TABLEemp ALTER address TYPE text;
移除數據
2 指定過期時間(同上)
2 刪除table或keyspace
DROP TABLE table_name
DROP KEYSPACE keyspace_name;
2 刪除columns和rows
DELETE last_name FROM emp WHEREempid=104 and deptid=15;
DELETE FROM emp WHERE empid=104 anddeptid=15;
使用collection類型
2 set類型
CREATE TABLE users (
user_id text PRIMARY KEY,
first_name text,
last_name text,
emails set<text>
);
n INSERT INTO users (user_id, first_name, last_name, emails) VALUES('frodo','Frodo', 'Baggins', {'f@baggins.com', 'baggins@gmail.com'});
n UPDATE users SET emails = emails + {'fb@friendsofmordor.org'} WHEREuser_id = 'frodo';
n UPDATE users SET emails = emails - {'fb@friendsofmordor.org'} WHEREuser_id = 'frodo';
n UPDATE users SET emails = {} WHERE user_id = 'frodo';
n DELETE emails FROM users WHERE user_id = 'frodo';
2 list類型
n ALTER TABLE users ADD top_places list<text>;
n UPDATE users SET top_places = [ 'rivendell', 'rohan' ] WHERE user_id= 'frodo';
n UPDATE users SET top_places = [ 'the shire' ] + top_places WHEREuser_id = 'frodo';
n UPDATE users SET top_places = top_places + [ 'mordor' ] WHEREuser_id = 'frodo';
n UPDATE users SET top_places[2] = 'riddermark' WHERE user_id ='frodo';
n DELETE top_places[3] FROM users WHERE user_id = 'frodo';
n UPDATE users SET top_places = top_places - ['rivendell'] WHEREuser_id = 'frodo';
2 map類型
n ALTER TABLE users ADD todo map<timestamp, text>;
n UPDATE users SET todo =
{ '2012-9-24' : 'entermordor',
'2012-10-2 12:00' : 'throwring into mount doom' }
WHERE user_id = 'frodo';
n UPDATE users SET todo['2012-10-2 12:00'] = 'throw my precious intomount doom'WHERE user_id = 'frodo';
n INSERT INTO users (user_id,todo) VALUES ('miaohan', { '2013-9-22 12:01' : 'birthday wishes to Bilbo', '2013-10-1 18:00' : 'Check into Inn of Prancing Pony' });
n DELETE todo['2012-9-24'] FROM users WHERE user_id = 'frodo';
n UPDATE users USING TTL 60 SET todo['2012-10-1'] = 'find water' WHEREuser_id = 'frodo';
注;可為上述三種集合類型的每個元素設置單獨的過期時間。
創建和使用索引
CREATE INDEXlast_name_key ON users(last_name);
SELECT * FROMusers WHERE last_name = 'Baggins'(需創建了索引才能在WHERE中使用該列進行查詢,暫無多列索引,需逐列分別建立索引)
輕量級事務
使用IF從句實現
n INSERT INTO emp(empid,deptid,address,first_name,last_name) VALUES(102,14,'luoyang','Jane Doe','li') IF NOT EXISTS;
n UPDATE emp SET address = 'luoyang' WHERE empid = 103 and deptid = 16IF last_name='zhang';
使用counter
用于記錄特定時間或處理的次數。對應的column需使用counter數據類型,該類數據一般存儲于專門的表中,且使用UPDATE載入并增減counter值,不使用INSERT插入counter值。只能在原數值的基礎上增減,不能為直接指定一個數值。
CREATEKEYSPACE counterks WITH REPLICATION = { 'class' : 'SimpleStrategy','replication_factor' : 3 };
CREATE TABLEcounterks.page_view_counts
(counter_valuecounter,
url_name varchar,
page_name varchar,
PRIMARY KEY (url_name, page_name)
);
UPDATEcounterks.page_view_counts
SET counter_value = counter_value + 1
WHERE url_name='www.datastax.com' ANDpage_name='home';
若原來不存在 WHERE條件中指定的內容,該條語句會將表中的url_name值置為'www.datastax.com'將page_name置為’home’,將 counter_value指定為默認初始值0加1。若WHERE條件中指定的內容存在,則將counter_value置為原來的 counter_value加1
UPDATEcounterks.page_view_counts
SET counter_value = counter_value + 2
WHERE url_name='www.baidu.com' ANDpage_name='map';
更多CQL內容請參見:http://www.datastax.com/documentation/cql/3.1/webhelp/index.html
6安全
三方面安全策略
? Client-to-node/node-to-node加密(SSL):加密傳輸的數據
? 基于登錄賬戶/密碼的認證:確定誰可以使用數據庫
? 對象授權管理:確定用戶可在在數據庫上干什么
6.1 SSL加密
6.1.1Client-to-node
準備證書
? 為每個節點產生私鑰/公鑰對
keytool-genkey -alias cassandra_vms00780 -keystore ~/keys/.keystore
? 導出公鑰部分到單獨的證書文件,并拷貝該文件到其他所有節點
keytool-export -alias cassandra_vms00780 -file ~keys/cassandra_vms00780.cer -keystore ~/keys/.keystore
? 將每個節點的證書添加到所有節點的信任庫中
keytool-import -v -trustcacerts -alias cassandra_vms00780 -file cassandra_vms00780.cer–keystore ~/keys/ .truststore
? 保證將.keystore和truststore文件分發到所有節點
? 確認.keystore文件只對Cassandradaemon可讀
編輯配置文件
配置cassandra.yaml文件中client_encryption_options部分的參數
client_encryption_options:
enabled: true
keystore: ~keys/.keystore## .keystore file路徑
keystore_password:<keystore password> ## 產生keystore時用的密碼
truststore: ~keys/.truststore
truststore_password:<truststore password>
require_client_auth:<true or false>
6.1.2node-to-node
準備證書
同上
編輯配置文件
配置cassandra.yaml文件中server_encryption_options部分的參數
server_encryption_options:
internode_encryption: <internode_option:all/none/dc/rack>
keystore: ~keys/.keystore
keystore_password: <keystore password>
truststore:~keys/.truststore
truststore_password: <truststorepassword>
require_client_auth: <true or false>
6.1.3在cqlsh中使用SSL
可在主目錄依據樣例文件cqlshrc.sample創建.cqlshrc文件
[authentication]
username = cassandra
password = cassandra
[connection]
hostname = localhost
port = 9160
factory =cqlshlib.ssl.ssl_transport_factory
[ssl]
certfile =~/keys/cassandra.cert
validate = true
[certfiles]
192.168.1.3 =~/keys/cassandra01.cert
192.168.1.4 =~/keys/cassandra02.cert
6.2內部認證
基于Cassandra控制的登錄賬戶和密碼
認證用的登錄名和經bcrypt散列的密碼存儲于system_auth.credentials表中
6.2.1配置
第一步
? 若要使用基于用戶名/密碼的認證機制,需要先配置cassandra.yaml文件中authenticator的值為 PasswordAuthenticator(該參數默認值為AllowAllAuthenticator,即,不進行任何認證)。這樣 cassandra會在system_auth.user創建一個超級用戶,用戶名和密碼均為cassandra。之后,配置system_auth這個 keyspace的replication factor為較大的值(詳見第5章使用創建、更新keyspace部分的內容)
認證語句
? ALTER USER
ALTER USERuser_name WITH PASSWORD 'password' (NOSUPERUSER| SUPERUSER)
注:SUPERUSER可更改其他用戶的密碼和SUPERUSER狀態(NOSUPERUSER或 SUPERUSER),但不能改變自己的SUPERUSER狀態。普通用戶只能更改自己的密碼。
? CREATE USER
CREATE USERuser_name WITH PASSWORD 'password' (NOSUPERUSER| SUPERUSER)
只有SUPERUSER可創建用戶,創建的用戶默認為NOSUPERUSER
? DROP USER
DROP USER user_name
只有SUPERUSER可刪除用戶,用戶不能自己刪除自己。
? LIST USERS
LIST USERS(為什么沒有結果???)
列出用戶
更改默認SUPERUSER
? 使用默認SUPERUSER也即cassandra登錄
./cqlsh -ucassandra -p Cassandra
? 新建另一SUPERUSER,之后刪除原cassandraSUPERUSER
create userus_yanzhaozhang with password 'cassandra' superuser;
drop usercassandra;
? 重啟cassandra,使用新的SUPERUSER登錄,執行后續操作。
6.2.2使用cqlsh登錄
若使用cqlsh登錄,可將認證信息存儲于.cqlshrc文本文件,放置在用戶主目錄中,以免重復錄入登錄信息。注意對該文本文件設置對應的權限以防信息泄露。
[authentication]
username = example_username
password = example_password
6.3內部授權
對象權限管理基于內部授權,與關系型數據庫GRANT/REVOKE語法類似。
首先要配置 cassandra.yaml中authorizer的值為CassandraAuthorizer(默認為AllowAllAuthorizer,允許 任何用戶的任何動作),設定為該值后會將授權信息存儲在system_auth.permissions表中。
之后,配置system_auth這個keyspace的replicationfactor為較大的值。
通過設置permissions_validity_in_ms選項調整權限有效期。
語法
GRANTpermission_name PERMISSION
| ( GRANT ALLPERMISSIONS ) ON resource TO user_name
REVOKE (permission_name PERMISSION )
| ( REVOKE ALLPERMISSIONS )
ON resourceFROM user_name
LISTpermission_name PERMISSION
| ( LIST ALLPERMISSIONS )
ON resource OF user_name
NORECURSIVE
其中permission_name為
? ALL
? ALTER
? AUTHORIZE
? CREATE
? DROP
? MODIFY
? SELECT
resource為
? ALL KEYSPACES
? KEYSPACE keyspace_name
? TABLE keyspace_name.table_name
6.4配置防火墻端口訪問
需在防火墻策略中開放一下端口
? 公共端口
n 22 ssh端口
n 8888 OpsCenter website端口
? Cassandra節點間端口
n 1024+ JMX reconnection/loopback端口
n 7000 Cassand集群內節點間通訊端口
n 7199 Cassandra JMX 監控端口
n 9160 Cassandra客戶端端口
? Cassandra OpsCenter 端口
n 61620 OpsCenter監控端口
n 61621 OpsCenter代理端口
7架構
7.1梗概
點對點分布式系統,集 群中各節點平等,數據分布于集群中各節點,各節點間每秒交換一次信息。每個節點的commit log捕獲寫操作來確保數據持久性。數據先被寫入memtable-內存中的數據結構,待該結構滿后數據被寫入SSTable-硬盤中的數據文件。所有的 寫內容被自動在集群中分區并復制。
Cassandra數據庫面向行。授權用戶可連接至任意數據中心的任意節點,并通過類似SQL的CQL查詢數據。集群中,一個應用一般包含一個keyspace,一個keyspace中包含多個表。
客戶端連接到某一節點發起讀或寫請求時,該節點充當客戶端應用與擁有相應數據的節點間的協調者(coordinator)以根據集群配置確定環中的哪個節點當獲取這個請求。
關鍵詞
? Gossip:點對點通信協議,用以Cassandra集群中節點間交換位置和狀態信息。
? Partitioner:決定如何在集群中的節點間分發數據,也即在哪個節點放置數據的第一個replica。
? Replica placement strategy:決定在哪些節點放置數據的其他replica。Cassandra在集群中的多個節點存儲數據的多份拷貝-replicas來確保可靠和容錯。
? Snitch:定義了復制策略用來放置replicas和路由請求所使用的拓撲信息
? cassandra.yaml文件:Cassandra主配置文件
? system:Cassandra的系統keyspace,存放table、keyspace的屬性信息等。而屬性信息可通過CQL或其他驅動設置。
7.2節點間通信
Cassandra使用點對點通訊協議gossip在集群中的節點間交換位置和狀態信息。gossip進程每秒運行一次,與至多3個其他節點交換信息,這樣所有節點可很快了解集群中的其他節點信息。
配置gossip(在cassandra.ymal中設置)
? cluster_name:節點所屬集群名,集群中每個節點應相同。
? listen_address:供其他節點連接至該節點的IP地址或主機名,當由localhost設為公共地址。
? seed_provider:逗號分隔的IP地址(種子列表),gossip通過種子節點學習環的拓撲,集群中各節點種子列表當相同。多數據中心集群中每個數據中心的種子列表當至少包含一個該中心內的節點。
? storage_port:節點間通訊端口,集群中各節點當一致。
? initial_token:用于single-node-per-token結構,節點在環空間只擁有一段連續的token范圍。
? num_tokens:用于virtual nodes,定義了節點在環空間所擁有的隨機分配的token數目。
失敗檢測與恢復
? gossip可檢測其他節點是否正常以避免將請求路由至不可達或者性能差的節點(后者需配置為dynamic snitch方可)。
? 可通過配置phi_convict_threshold來調整失敗檢測的敏感度。
? 對于失敗的節點,其他節點會通過gossip定期與之聯系以查看是否恢復而非簡單將之移除。若需強制添加或移除集群中節點需使用nodetool工具。
? 一旦某節點被標記為失敗,其錯過的寫操作會有其他replicas存儲一段時間(需開啟hinted handoff,若節點失敗的時間超過了max_hint_window_in_ms,錯過的寫不再被存儲。)Down掉的節點經過一段時間恢復后需執行 repair操作,一般在所有節點運行nodetool repair以確保數據一致。
7.3數據復制和分發
Cassandra中分發、復制同時進行。Cassandra被設計為點對點系統,會創建數據的多個副本存儲在集群中的一組節點中。Cassandra中數據被組織為表,由primary key標識,primary key決定數據將被存儲在哪個節點。
需指定的內容
Virtual nodes:指定數據與物理節點的所屬關系
Partitioner:在集群內劃分數據
Replicationstrategy:決定如何處理每行數據的replicas
Snitch:定義replicationstrategy放置數據的replicas時使用的拓撲信息
一致性哈希
表中每行數據由 primary key標識,Cassandra為每個primarykey分配一個hash值,集群中每個節點擁有一個或多個hash值區間。這樣便可根據 primary key對應的hash值將該條數據放在包含該hash值的hash值區間對應的節點中。
虛擬節點
使用虛擬接電視數據在集群中的分布
若不使用虛擬節點則需 手工為集群中每個節點計算和分配一個token。每個token決定了節點在環中的位置以及節點應當承擔的一段連續的數據hash值的范圍。如上圖上半部 分,每個節點分配了一個單獨的token代表環中的一個位置,每個節點存儲將row key映射為hash值之后落在該節點應當承擔的唯一的一段連續的hash值范圍內的數據。每個節點也包含來自其他節點的row的副本。而是用虛擬節點允 許每個節點擁有多個較小的不連續的hash值范圍。如上圖中下半部分,集群中的節點是用了虛擬節點,虛擬節點隨機選擇且不連續。數據的存放位置也由row key映射而得的hash值確定,但是是落在更小的分區范圍內。
使用虛擬節點的好處
? 無需為每個節點計算、分配token
? 添加移除節點后無需重新平衡集群負載
? 重建死掉的節點更快
? 改善了在同一集群使用異種機器
數據復制
Cassandra在 多個節點中存放replicas以保證可靠性和容錯性。replicationstrategy決定放置replicas的節點。replicas的總數 由復制因子- replication factor確定,比如因子為2代表每行有兩份拷貝,每份拷貝存儲在不同的節點中。所有的replicas無主從之分。replication factor通常不能超過集群中節點總數。然而,可現增加replication facto之后在將節點增至期望的數量。當replication facto超過總結點數時,寫操作被拒絕,但讀操作可進行,只要滿足期望的一致性級別。
當前有兩種可用的復制策略:
? SimpleStrategy:僅用于單數據中心,將第一個replica放在由partitioner確定的節點中,其余的replicas放在上述節點順時針方向的后續節點中。
? NetworkTopologyStrategy:可用于較復雜的多數據中心。可以指定在每個數據中心分別存儲多少份replicas。在每個數據中心放 置replicas的方式類似于SimpleStrategy,但傾向于將replicas放在不同rack,因為同一rack的節點傾向于同時失敗。配 置每個數據中心分別放置多少replicas時要考慮兩個主要方面:(1)可滿足本地讀而非跨數據中心讀;(2)失敗場景。兩種常用的配置方式為(1)每 個數據中心兩份replicas,(2)每個數據中心3份replicas。當然,用于特殊目的的非對稱配置也是可以的,比如在讀操作較頻繁的數據中心配 置3份replicas而在用于分析的數據中心配置一份replicas。
復制策略在創建keyspace時指定,如
CREATEKEYSPACE Excelsior WITH REPLICATION = { 'class' : 'SimpleStrategy','replication_factor' : 3 };
CREATEKEYSPACE "Excalibur" WITH REPLICATION = {'class' :'NetworkTopologyStrategy', 'dc1' : 3, 'dc2' : 2};
其中dc1、dc2這些數據中心名稱要與snitch中配置的名稱一致。
7.4Partitioners
在Cassandra中,table的每行由唯一的primarykey標識,partitioner實際上為一hash函數用以計算primary key的token。Cassandra依據這個token值在集群中放置對應的行。
三種partitioner(在cassandra.yaml中設置)
? Murmur3Partitioner:當前的默認值,依據MurmurHash哈希值在集群中均勻分布數據。
? RandomPartitioner:依據MD5哈希值在集群中均勻分布數據。
? ByteOrderedPartitioner:依據行key的字節從字面上在集群中順序分布數據。(不推薦使用)
Murmur3Partitioner 和RandomPartitioner使用token向每個節點指派等量的數據從而將keyspace中的表均勻分布在環中,即使不同的表使用不同的 primary key。讀寫請求均被均勻的分布。ByteOrderedPartitioner允許通過primary key順序掃描(可通過index達到同樣目的),但已引起如下問題(1)較復雜的負載均衡,(2)順序的寫易導致熱點,(3)多表不均勻的負載均衡。
注意:若使用虛擬節點(vnodes)則無需手工計算tokens。若不使用虛擬節點則必須手工計算tokens將所得的值指派給cassandra.ymal主配置文件中的initial_token參數。具體可參考:http://www.datastax.com/documentation/cassandra/2.0/webhelp/index.html#cassandra/architecture/../configuration/configGenTokens_c.html
7.5Snitches
提供網絡拓撲信息,用以確定向/從哪個數據中心或者網架寫入/讀取數據。
注意:(1)所有節點需用相同的snitch;(2)集群中已插入數據后由更改了snitch則需運行一次fullrepair。
? Dynamic snitching
監控從不同replica讀操作的性能,選擇性能最好的replica。dynamic snitch默認開啟,所有其他snitch會默認使用dynamic snitch 層。
? SimpleSnitch
默認值,用于單數據中心部署,不使用數據中心和網架信息。使用該值時keyspace復制策略中唯一需指定的是replication factor
? RackInferringSnitch
根據數據中心和網架確定節點位置,而數據中心及網架信息又有節點的IP地址隱含指示。
? PropertyFileSnitch
根據數據中心和網架確 定節點位置,而網絡拓撲信息又由用戶定義的配置文件cassandra-topology.properties 獲取。在節點IP地址格式不統一無法隱含指示數據中心及網架信息或者復雜的復制組中使用該值。需注意的是:(1)配置文件中數據中心名需與 keyspace中復制策略中指定的數據中心名稱一致;(2)配置文件中需包含集群中任一節點;(3)集群中各節點內cassandra- topology.properties配置文件需相同。
? GossipingPropertyFileSnitch
? 在cassandra-rackdc.properties配置文件中定義本節點所屬的數據中心和網架,利用gossip協議與其他節點交換該信息。若從 PropertyFileSnitch切至該值,則需逐節點逐次更新值為GossipingPropertyFileSnitch以確保gossip有時 間傳播信息。
? EC2Snitch
用于部署在Amazon EC2中且所有節點在單個區域中的集群。
? EC2MultiRegionSnitch
? 用于部署在AmazonEC2中,且節點跨多個區域的集群。
7.6客戶端請求
client連接至節點并發出read/write請求時,該node充當client端應用與包含請求數據的節點(或replica)之間的協調者,它利用配置的partitioner和replicaplacement策略確定那個節點當獲取請求。
7.6.1寫請求
協調者 (coordinator)將write請求發送到擁有對應row的所有replica節點,只要節點可用便獲取并執行寫請求。寫一致性級別(write consistency level)確定要有多少個replica節點必須返回成功的確認信息。成功意味著數據被正確寫入了commit log個memtable。
上例為單數據中心,11個節點,復制因子為3,寫一致性等級為ONE的寫情況。
7.6.2多數據中心的寫請求
基 本同上,但會在各數據中心分別選擇一個協調者以處理該數據中心內的寫請求。與client直接連接的coordinator節點只需將寫請求發送到遠程數 據中心的coordinator一個節點即可,剩余的由該coordinator完成。若一致性級別設置為ONE或者LOCAL_QUORUM則僅與直接 協調者位于同一數據中心的節點需返回成功確認。
上例為雙單數據中心,各11個節點,復制因子為6,寫一致性等級為ONE的寫情況。
7.6.3讀請求
? 直接讀請求
? 后臺讀修復請求
與直接讀請求聯系的replica數目由一致性級別確定。后臺讀修復請求被發送到沒有收到直接讀請求的額外的replica,以確保請求的row在所有replica上一致。
協調者首先與一致性級別確定的所有replica聯系,被聯系的節點返回請求的數據,若多個節點被聯系,則來自各replica的row會在內存中作比較,若不一致,則協調者使用含最新數據的replica向client返回結果。
同時,協調者在后臺聯系和比較來自其余擁有對應row的replica的數據,若不一致,會向過時的replica發寫請求用最新的數據進行更新。這一過程叫read repair。
上例為單數據中心,11個節點,復制因子為3,一致性級別為QUORUM的讀情況。
8數據庫內部
8.1數據管理
使用類似Log- StructuredMerge Tree的存儲結構,而非典型的關系型數據庫使用的B-Tree結構。存儲引擎連續的將數據以追加的模式寫物磁盤并持續存儲數據。節點間/內的操作并行運 行。因不使用B-Tree故無需協同控制,在寫時不必執行更新。Cassandra在SSD中性能表現極佳。
高吞吐量和低延遲
操作并行運行,吞吐量和延遲相互獨立。log-structured設計避免詢盤開銷。去除on-disk數據修改,省時且延長SSD壽命。無on-disk型的數據修改故無需鎖定寫請求這樣的協同控制。無主、從,在所有節點運行同樣的代碼。
單獨的表目錄
/var/lib/cassandra/data/ks1/cf1/ks1-cf1-ja-1-Data.db
其中/var/lib /cassandra/data/為cassandra.yaml中指定的數據文件目錄。ks1為keyspace名cf1/為 columnfamilies名。這樣可將表連接至選定的目標位置以便于將活躍的表移到更快的存儲介質,或者將表分不到多個可用的存儲設備以均衡負載
8.2關于寫
復制的角色
通過在多個同級節點創建數據的多個副本保證可靠性和容錯。表是非關系型的,無需過多額外工作來維護關聯的表的完整性,因此寫操作較關系型數據庫快很多。
寫過程
先將數據寫進內存中的 數據結構memtable,同時追加到磁盤中的commitlog中。表使用的越多,對應的memtable應越大,cassandra動態的為 memtable分配內存,也可自己手工指定。memtable內容超出指定容量后memtable數據(包括索引)被放進將被刷入磁盤的隊列,可通過 memtable_flush_queue_size配置隊列長度。若將被刷入磁盤的數據超出了隊列長度,cassandra會鎖定寫。memtable 表中的數據由連續的I/O刷進磁盤中的SSTable,之后commit log被清空。每個表有獨立的memtable和SSTable。
8.3關于更新、刪除和hinted handoff writes
更新(cassandra中插入重復的primarykey也被看做是更新操作)
不直接在磁盤中原地更新而是先在memtable進行所有的更新。最后更新內容被刷入磁盤存儲在新的SSTable中,僅當column的時間戳比既存的column更新時才覆蓋原來的數據。
刪除
? 不會立即從磁盤移除刪除的數據
被刪除的數據會被tombstone標記以指定其狀態,它會存在一定的時間(由gc_grace_seconds指定),超出該時間后compaction進程永久刪除該column。
? 若不例行性的執行節點repair操作,被刪除的column可能重新出現
若刪除期間節點 down掉,被標記為tombstone的column會發送信號給Cassandra使其重發刪除請求給該replica節點。若replica在 gc_grace_seconds期間復活,會最終受到刪除請求,若replica在gc_grace_seconds之后復活,節點可能錯過刪除請求, 而在節點恢復后立即刪除數據。需定期執行節點修復操作來避免刪除數據重現。
hinted handoff writes
在不要求一致性時確保 寫的高可用,在cassandra.yaml中開啟該功能。執行write操作時若擁有對應row的replica down掉了或者無回應,則協調者會在本地的system.hints表中存儲一個hint,指示該寫操作需在不可用的replica恢復后重新執行。默 認hints保存3小時,可通過max_hint_window_in_ms改變該值。
提示的write不 計入consistencylevel中的ONE,QUORUM或ALL,但計入ANY。ANY一致性級別可確保cassandra在所有replica 不可用時仍可接受write,并且在適當的replica可用且收到hint重放后該write操作可讀。
移除節點后節點對應的hints自動移除,刪除表后對應的hints也會被移除。
仍需定期執行repair(避免硬件故障造成的數據丟失)
8.4關于讀
從SSD并行隨機讀取,延時極低(不推薦cassandra使用轉盤式硬盤)。以partition key讀/寫,消除了關系型數據庫中復雜的查詢。
讀SSTable
首先檢查Bloom filter,每個SSTable都有一個Bloomfilter,用以在進行任何磁盤I/O前檢查請求的partition key對應的數據在SSTable中存在的可能性。若數據很可能存在,則檢查Partition key cache(Cassandra表partition index的緩存),之后根據index條目是否在cache中找到而執行不同步驟:
? 找到
從compression offset map中查找擁有對應數據的壓縮快。
從磁盤取出壓縮的數據,返回結果集。
? 未找到
搜索Partition summary(partition index的樣本集)確定index條目在磁盤中的近似位置。
從磁盤中SSTable內取出index條目。
從compression offset map中查找擁有對應數據的壓縮快。
從磁盤取出壓縮的數據,返回結果集。
回顧插入/更新數據
讀的過程
由insert/update過程可知,read請求到達某一節點后,必須結合所有包含請求的row中的column的SSTable以及memtable來產生請求的數據。
例如,要更新包含用戶 數據的某個row中的email 列,cassandra并不重寫整個row到新的數據文件,而僅僅將新的email寫進新的數據文件,username等仍處于舊的數據文件中。上圖中紅 線表示Cassandra需要整合的row的片段用以產生用戶請求的結果。為節省CPU和磁盤I/O,Cassandra會緩存合并后的結果,且可直接在 該cache中更新row而不用重新合并。
8.5關于事務和協同控制
不支持RDBMS中具有回滾和鎖定機制的ACID事務,但提供了一定程度的原子性(行級)、隔離性(行級)、持久性和eventual/tunable 類型的一致性(因不支持連接和外鍵,故不提供ACID場景下的一致性)。
? 原子性
row-level, 對一個row的插入/更新被當做一個原子操作。不支持要么都做要么都不做的多行插入/更新。不支持在一個replica上write成功而在其他 replica上write失敗的回滾。用時間戳確定column的最新更新。若多個session同時更新同樣的column則使用最近的更新。
? 一致性
l Tuneable一致性
提供partition容錯。用戶可以以單個操作為基礎決定需多少個節點接收DML操作或響應SELECT操作。
l Linearizable一致性
l 輕量事務(compare-and-set)的一系列隔離級別。在tuneable一致性不足以滿足要求時使用,如執行無間斷的相繼操作或同時/不同時運 行一個操作產生同樣的結果。Cassandra2.0使用類似2-phase commit的Paxos consensus協議實現Linearizable一致性。(為支持該一致性引入了SERIAL類型的consistency level及在CQL中使用了帶IF從句的輕量事務)
? 隔離性
Cassandra2.0開始支持row-level的隔離性。對行的寫操作在完成之前對其他用戶不可見。
? 持久性
同時將數據寫入內存中的memtable及磁盤中的commit log。服務器故障時若memtable尚未刷入磁盤,在故障恢復后可重放commit log恢復丟失數據。這提供了本地持久性。數據在其他節點的副本加強了持久性。
輕量事務
Cassandra2.0中引入,彌補Tuneable一致性。
n INSERT INTO emp(empid,deptid,address,first_name,last_name) VALUES(102,14,'luoyang','Jane Doe','li') IF NOT EXISTS;
n UPDATE emp SET address = 'luoyang' WHERE empid = 103 and deptid = 16IF last_name='zhang';
8.6配置數據一致性
Cassandra中,一致性級別可配置,以確定請求的數據如何在不同的replica保持一致性,從而平衡響應時間和數據精確性。
? 寫一致性
指明在返回確認至客戶端前,write操作必須成功的replica數。
l ANY:write至少在一個replica成功。即使所有replica 都down掉,在寫hinted handoff后write仍成功。在replica恢復后該write可讀。
l ONE:write必須成功寫入至少一個replica的commit log和memtable。
l TWO:至少兩個
l THREE:至少三個
l QUORUM:至少(replication_factor/ 2) + 1個
l LOCAL_QUORUM:至少(replication_factor/ 2) + 1個,且與協調者處于同一數據中心
l EACH_QUORUM:所有數據中心,至少(replication_factor/ 2) + 1個
l ALL:全部
l SERIAL:至少(replication_factor/ 2) + 1個,用于達成輕量事務的linearizable consistency
需注意的是:實際上write還是會被發到所有相關的replica中,一致性級別只是確定必需要反饋的replica數。
? 讀一致性
指明在返回數據值客戶端前,需要相應read請求的相關replica數。Cassandra從這些數量的replica中根據時間戳檢查最新的數據。級別同寫一致性。
可通過cqlsh命令CONSISTENCY設置keyspace的一致性,也可編程設置一致性。
9操作
9.1監控Cassandra集群
工具:nodetool utility、DataStaxOpsCenter、JConsole
? nodetool utility:Cassandra發行版附帶的命令行工具,用于監控和常規數據庫操作。一些常用命令如status、cfstats、cfhistograms、netstats、tpstats等。
? DataStax OpsCenter:圖形用戶界面工具,從中央控制臺監控和管理集群中所有節點。
? JConsole:JMX兼容工具用以監控java應用程序,提供Overview、Memory、Thread、Classes、VM summary、Mbeans方面的信息。
9.2調整Bloom filters
Bloom filters用以在執行I/O前確定SSTable是否含特定的row。用于index掃描而不用于range掃描。通過 bloom_filter_fp_chance參數配置其屬性值,范圍為0至1.0(關閉),值越大則使用的內存越少,但也意味著若SSTable由較多 碎片則導致較高的磁盤I/O。默認值依賴于compaction_strategy類型。值的設置依賴工作負荷,如,若需在一特定表上運行繁重的scan 則需將bloom_filter_fp_chance設置高一點。
通過如下語句設置:
ALTER TABLEaddamsFamily WITH bloom_filter_fp_chance = 0.1;
設置好后需使用Initiatecompaction或Upgrade SSTables方式之一重新產生Bloom filter。
9.3數據緩存
兩類cache:partitionkey cache和row cache
? partition key cache:Cassandra表partition index的cache
? row cache:一個row首次被訪問后整個row(合并自多個對應的SSTable及memtable)被放在row cache中以便于后續對改row的訪問能直接由內存獲取數據。
對于很少訪問的archive表當禁用緩存。
開啟與配置cache
? 開啟
CREATE TABLEusers (
userid text PRIMARY KEY,
first_name text,
last_name text,
)
WITH caching ='all';
? 配置
在cassandra.yaml中,調整下列參數;
l key_cache_keys_to_save
l key_cache_save_period
l key_cache_size_in_mb
l row_cache_keys_to_save
l row_cache_size_in_mb
l row_cache_save_period
l row_cache_provider
工作原理:
第一個read操作直 接命中rowcache,從內存取出數據。第二個read操作為命中row cache,但命中partition key cache,并由此整合所有相關的SSTable及memtable中的片段為請求的row,返回row并寫進row cache。
cache使用優化建議
? 將很少請求的數據或row很長的數據放在cache較小或不使用cache的表中
? 用較多的節點部署各節點負載較輕的集群
? 邏輯上將read稠密的數據分開在離散的表中
9.4配置memtable吞吐量
可改善write性 能。Cassandra在commit logspace threshold超出時將memtables內容刷進磁盤創建SSTable。在cassandra.ymal中配置commit log space threshold來調整memtable吞吐量。配置的值依賴于數據和write負載。下列兩種情況可考慮增加吞吐量:
? write負載包含大量在小數據集上的更新操作
? 穩定持續的寫操作
9.5Compaction與Compression
9.5.1Compaction
周期性的后臺進程。Compaction期間Cassandra通過整合row片段合并SSTable、移除過期的tombstones、重建索引等,并在新SSTable合并完成后移除舊的SSTable。
兩類Compaction
? SizeTieredCompactionStrategy
收集尺寸相近的SSTable合并為一個較大的SSTable。
? LeveledCompactionStrategy
創建相對較小的SSTable,尺寸被固定為不同等級(L0、L1、L2……),同一級內SSTable大小相同,每差一個等級尺寸差10倍。SSTable從較小的等級逐漸合并至較高的等級。
Compaction操作會臨時增加磁盤I/O,但完成后可改善read性能。
開啟與配置Compaction
? 使用CQL語句CREATE/ALTER TABLE
l ALTER TABLE users WITH
compaction = { 'class' : 'LeveledCompactionStrategy', 'sstable_size_in_mb' : 10 }
l ALTER TABLE users
WITH compaction ={'class' : 'SizeTieredCompactionStrategy','min_threshold' : 6 }
更多屬性參見CQL keyspace and table properties.
? 配置cassandra.yaml文件
l snapshot_before_compaction
l in_memory_compaction_limit_in_mb
l multithreaded_compaction
l compaction_preheat_key_cache
l concurrent_compactors
l compaction_throughput_mb_per_sec
9.5.2Compression
通過減少數據體積和磁盤I/O來最大化存儲能力。大大提升讀性能且不會像傳統關系型數據庫中的Compression操作降低write性能。
什么時候執行Compression
適用于擁有大量的row且每個row與其他row有一樣的column或盡可能多相同的column的表。越相似壓縮比越高,性能提升越明顯。row具有差異較大的column集的表不適于Compression。如Dynamic表。
配置好compression后后續創建的SSTable被壓縮,之前已經存在的SSTable不被立即壓縮直到正常的Cassandracompaction進程開始。可使用nodetool upgradesstables命令強制壓縮既存的SSTable
配置Compression
? 禁用
CREATE TABLEDogTypes (
block_id uuid,
species text,
alias text,
population varint,
PRIMARY KEY (block_id)
)
WITH compression = {'sstable_compression' : '' };
? 開啟
CREATE TABLEDogTypes (
block_id uuid,
species text,
alias text,
population varint,
PRIMARY KEY (block_id)
)
WITH compression = {'sstable_compression' : 'LZ4Compressor' };
? 調整
ALTER TABLECatTypes
WITH compression = { 'sstable_compression' :'DeflateCompressor', 'chunk_length_kb' : 64 }
9.6調整Java資源
性能下降或內存消耗過多時需考慮調整Java資源。有兩個文件用于Cassandra中環境設置:
? comf/cassandra-env.sh:配置JVM
? bin、cassandra-in.sh:配置Cassandra環境變量
調整Heap尺寸時MAX_HEAP_SIZE與HEAP_NEWSIZE要同時設置,前者設置JVM最大heap尺寸,后者設置新生代的尺寸,新生代尺寸越大垃圾回收暫停時間越長,反之垃圾回收消耗越大。
當前默認配置:
系統內存 |
Heap 大小 |
少于 2GB |
系統內存的1/2 |
2GB t到 4GB |
1GB |
大于 4GB |
系統內存的1/4,但不會超過8GB |
heap大小并非越大越好:首先Java6處理8GB以上的垃圾收集的能力會迅速縮減;其次會減少操作系統緩存頁所能使用的內存。
Cassandra1.2 以后版本Bloomfilter和compression offset map是off-heap的,不算在JVM的heap之內。Cassandra2.0后partition summary也是off-heap的。若在Cassandra中使用JNA庫,row cache也會升級為off-heap。這些可幫減少heap大小,增強JVM GC性能,從而增加Cassandra高效處理每個節點中數據的能力。
若GC頻發發生且在適度的時間完成表明JVM GC壓力過大,此時需作出增加節點、降低cache大小、調整JVM中有關GC的參數等補救措施。
JavaManagement Extensions (JMX)提供了管理和監控Java應用和服務的各種工具。如JConsole,、the nodetool utility和 DataStax OpsCenter這些JMX兼容工具。
comf/cassandra-env.sh中其他相關參數
? com.sun.management.jmxremote.port
? com.sun.management.jmxremote.ssl
? com.sun.management.jmxremote.authenticate
? -Djava.rmi.server.hostname
9.7修復 node
使用nodetool的repair命令,修復與給定的數據范圍相關的replica間的不一致性。在下屬情形運行修復:
? 規律的、計劃的集群維護操作期間(除非沒有執行過delete)
? 節點恢復后
? 在包含較少被訪問的數據的節點上
? 在down掉的節點更新數據
運行節點修復的方針:
? 常規修復操作執行次數由gc_grace值硬性規定。需在該時間內在每個節點至少運行一次修復操作。
? 同時在多于一個的節點運行常規修復時需謹慎,最好在低峰期規律運行修復。
? 在很少delete或overwrite數據的系統中,可增加gc_grace的值。
修復操作消耗磁盤I/O,可通過下述途徑減輕:
? 使用nodetool的compactionthrottling選項。
? 使用nodetoolsnapshot之后從snapshot執行修復。
修復操作會導致 overstreaming(問題源于Cassandra內部Merkletrees數據結構)。比如只有一個損壞的partition但卻需發送很多的 stream,且若節點中存在的partition越多問題越嚴重。這會引起磁盤空間浪費和不必要的compaction。可使用subrange 修復來減輕overstreaming。subrange repair只修復屬于節點的部分數據。
9.8添加/移除節點或數據中心
? 在既存集群中添加節點
以使用vnodes的節點為例(推薦此種方式,虛擬節點相關內容見第7節)
1. 在新節點安裝Cassandra,關閉cassandra,清除數據。
2. 在cassandra.yaml和cassandra-topology.properties中配置如下屬性:
l cluster_name
l listern_address/broadcast_address
l endpoint_snitch
l num_tokens
l seed_provider
3. 逐個啟動新節點中的cassandra,不同節點的初始化之間保持兩分鐘的間隔。可用nodetool netstats監控啟動和數據流處理
4. 待 所有新節點運行起來后逐個在每個之前已存在的節點執行nodetool cleanup來移除不再屬于這些節點的key。在下一個節點執行nodetool cleanup前必須等上一個節點中的nodetool cleanup結束。另外cleanup操作可考慮在低峰期進行。
? 向既存集群中添加數據中心
以使用vnodes的節點構成的集群為例
1. 確保keyspace使用NetworkTopologyStrategy復制策略
2. 對于每個新節點在cassandra.yaml中設置如下屬性
l auto_bootstrap: false.
l 設置其他與所屬集群匹配的屬性(參見上一部分:在既存集群中添加節點)
3. 根據設置的snitch類型在各新節點配置對應的指明網絡拓撲的配置文件(無需重啟)
4. 確保使用的客戶端不會自動探測新的節點。
5. 若使用QUORUM一致性級別,需檢查LOCAL_QUORUM或EACH_QUORUM一致性級別是否滿足多數據中心的要求
6. 逐個在每個節點開啟cassandra。注意初始化時間間隔。
7. 所有節點運行起來后執行下列操作
? 替換死掉的節點
以使用vnodes的節點構成的集群為例
1. 用nodetool status命令確認環中死掉的節點,從輸出中記錄該節點的HOST ID。
2. 添加并啟動新的替代節點(參見:在既存集群中添加節點)
3. 使用nodetool removenode命令根據記錄的死亡節點的HOST ID從集群中移除死掉的節點。
? 移除數據中心
1. 確認沒有client正在向數據中心內的任何節點寫數據
2. 在數據中心內的各節點中執行nodetool repair以確保數據從該中心得到正確的傳播。更改所有的keyspace屬性確保不再引用即將移除的數據中心。
3. 在數據中心內的各節點分別運行nodetool decommission
9備份恢復
Cassandra通 過為磁盤中的數據文件(SSTable文件)創建快照來備份數據。可為單個表、單個keyspace、所有keyspace創建快照。可用并行SSH工具 為整個集群創建快照。創建時不保證所有replica一致,但在恢復快照時Cassandra利用內建的一致性機制保持一致性。創建了系統范圍的快照后可 開啟增量備份只備份自上次快照以來變化了的數據(每當一個SSTable被flush后,一個對應的硬鏈接被拷貝至與/snapshot同級的 /backups子目錄(需使用JNA))。
若在Cassandra中使用了JNA,則快照通過硬鏈接創建。否則會因將文件拷貝至不同的位置而增加磁盤I/O。
9.1創建快照
在每個節點執行nodetoolsnapshot命令為節點創建快照。也可通過并行SSH工具(如pssh)運行nodetool snapshot創建全局的快照。
$ nodetool -h localhost -p 7199 snapshot demdb
執行命令后首先會將 內存中的數據刷進磁盤,之后為每個keyspace的SSTable文件創建硬鏈接。快照的默認位置為/var/lib/cassandra/data /<keyspace_name>/<table_name>/snapshots。其中/var/lib/cassandra /data部分依據數據目錄設置而不同。
要保證空間充足,創建后可考慮移至其他位置。
9.2刪除快照
創建新的快照并不會自動刪除舊的快照,需在創建新快照前通過nodetool clearsnapshot命令移除舊的快照。
$ nodetool -h localhost -p 7199 clearsnapshot
同樣可通過并行SSH工具(如pssh)運行nodetoolclearsnapshot一次刪除所有節點的快照。
9.3啟用增量備份
默認不開啟,可通過在各節點的cassandra.yaml配置文件中設置incremental_backups為true來開啟增量備份。開啟后會為每個新的被刷入的SSTable創建一個硬鏈接并拷貝至數據目錄的/backups子目錄。
Cassandra不會自動刪除增量備份文件,創建新的快照前需手工移除舊的增量備份文件。
9.4從快照恢復數據
需所有的快照文件,若 使用了增量備份還需快照創建之后所有的增量備份文件。通常,在從快照恢復數據前需先truncate表。(若備份發生在delete前而恢復發生在 delete后且沒truncate表時,則不能得到最原始的數據,因為直到compaction操作發生前被標記為tombstone的數據與原始數據 處于不同的SSTable中,所以恢復包含原始數據的SSTable不會移除被標記被tombstone的數據,這些數據仍然顯示為將被刪除)。
可以用如下方式從快照恢復數據
? 使用sstableloader工具
http://www.datastax.com/documentation/cassandra/2.0/webhelp/cassandra/tools/toolsBulkloader_t.html
? 先拷貝snapshot目錄中的快照文件至相應數據目錄。之后通過JConsole調用column family MBean 中的JMX方法loadNewSSTables()或者使用nodetool refresh命令而不調用上述方法。
? 使用重啟節點的方式
1. 若恢復單節點則先關閉該節點,若恢復整個集群則需先關閉所有節點
2. 清除/var/lib/cassandra/commitlog中的所有文件
3. 刪除<data_directory_location>/<keyspace_name>/<table_name>中所有*.db文件
4. 拷 貝最新<data_directory_location>/<keyspace_name> /<table_name>/snapshots/<snapshot_name>的快照文件 至<data_directory_location>/<keyspace_name>/<table_name>/snapshots/<snapshot_name>
5. 若 使用了增量備份則還需拷貝<data_directory_location>/<keyspace_name> /<table_name>/backups中的內容至<data_directory_location> /<keyspace_name>/<table_name>
6. 重啟節點
7. 運行nodetool repair
10工具
? nodetool:管理Cassandra集群的命令行工具
? sstableloader:載入大量外部數據至一集群;將已經存在的SSTable載入到另外一個節點數不同或者復制策略不同的集群;從快照恢復數據。上述操作無需停機。
? cassandra:啟動cassandra 服務器進程
? cassandra-stress:基于java的Cassandra集群壓力測試工具。
? cassandra-shuffle:在不停機的狀態下將single-token-per-node的結構轉化為使用虛擬節點的結構。
? sstablescrub:清洗指定的表的SSTable。
? sstable2json/json2sstable:前者將磁盤中表示表的SStable轉化為JSON格式的文檔,用于調試和測試目的;后者做反向轉換。
? sstablekeys:sstable2json –e 的縮寫,僅作用于key。
? sstableupgrade:將特定表中或快照中的SSTable升級至匹配當前Cassandra版本。
參考
http://www.datastax.com/documentation/cassandra/2.0/webhelp/index.html