2015/11/16

如何在 CentOS 安裝 Cassandra

Cassandra 屬於 column-family 類型的 NoSQL database,特性是 ring cluster network topology,支援類似 SQL 語法的 CQL,適合儲存依照時間排序且scheme固定的大量資料。以下嘗試在 centos 安裝 cassandra。

單一節點

tar zxvf apache-cassandra-2.2.3-bin.tar.gz -C /usr/share

#啟動
/usr/share/apache-cassandra-2.2.3/bin/cassandra

資料會放在
/usr/share/apache-cassandra-2.2.3/data 這個目錄中

系統紀錄放在
/usr/share/apache-cassandra-2.2.3/logs 這個目錄中

然後參考 cassandra Getting Started 的範例,使用 CQL 測試這個 DB。

// 建立資料庫 mykeyspace
CREATE KEYSPACE mykeyspace
WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 };

// 使用資料庫
USE mykeyspace;

// 建立 table: users
CREATE TABLE users (
  user_id int PRIMARY KEY,
  fname text,
  lname text
);


// insert 三筆測試資料
INSERT INTO users (user_id,  fname, lname)
  VALUES (1745, 'john', 'smith');
INSERT INTO users (user_id,  fname, lname)
  VALUES (1744, 'john', 'doe');
INSERT INTO users (user_id,  fname, lname)
  VALUES (1746, 'john', 'smith');

// 取得 users 所有資料
SELECT * FROM users;

 user_id | fname | lname
---------+-------+-------
    1745 |  john | smith
    1744 |  john |   doe
    1746 |  john | smith

(3 rows)

// 針對 lname 建立 index
CREATE INDEX ON users (lname);

// 條件搜尋
SELECT * FROM users WHERE lname = 'smith';

 user_id | fname | lname
---------+-------+-------
    1745 |  john | smith
    1746 |  john | smith

直接用 kill -9 停止此單一節點的 cassandra 的 process。

ps aux | grep cassandra
kill -9 20109

兩個節點

在兩台機器上,都分別先將單一節點的設定方式做好。記得一定要先以單機方式先啟動一次,否則會出現 Token 錯誤的問題。

使用 /usr/share/apache-cassandra-2.2.3/tools/bin/token-generator,計算這兩個節點在 Murmur3Partitioner 時,token 分別要設定為多少?

[root@server bin]# /usr/share/apache-cassandra-2.2.3/tools/bin/token-generator
Token Generator Interactive Mode
--------------------------------

 How many datacenters will participate in this Cassandra cluster? 2
 How many nodes are in datacenter #1? ^C[root@kokola bin]# ./token-generator
Token Generator Interactive Mode
--------------------------------

 How many datacenters will participate in this Cassandra cluster? 1
 How many nodes are in datacenter #1? 2

DC #1:
  Node #1:  -9223372036854775808
  Node #2:                     0

然後分別編輯兩台機器上的 /usr/share/apache-cassandra-2.2.3/conf/cassandra.yaml

- seeds: "127.0.0.1"

改為

- seeds: "192.168.1.11,192.168.1.12"

listen_address: localhost

分別改為各自的 IP: 192.168.1.11,192.168.1.12

listen_address: 192.168.1.11

在 192.168.1.11 增加一行

initial_token: -9223372036854775808

在 192.168.1.12 則改為

initial_token: 0

然後分別啟動兩台機器的 cassandra。

就可以在第二台機器,用 CQL 取得剛剛在單一節點時建立的 mykeyspace

[root@server bin]# ./cqlsh
Connected to Test Cluster at 127.0.0.1:9042.
[cqlsh 5.0.1 | Cassandra 2.2.3 | CQL spec 3.3.1 | Native protocol v4]
Use HELP for help.
cqlsh> use mykeyspace ;
/usr/share/apache-cassandra-2.2.3/bin/../lib/cassandra-driver-internal-only-2.7.2.zip/cassandra-driver-2.7.2/cassandra/cluster.py:3331: DeprecationWarning: ResponseFuture.result timeout argument is deprecated. Specify the request timeout via Session.execute[_async].
cqlsh:mykeyspace> 
cqlsh:mykeyspace> select * from users;

 user_id | fname | lname
---------+-------+-------
    1745 |  john | smith
    1744 |  john |   doe
    1746 |  john | smith

(3 rows)

可以用 nodetool 查看 cluster 的狀態

[root@server bin]# ./nodetool -h localhost status
Datacenter: datacenter1
=======================
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
--  Address       Load       Tokens       Owns    Host ID                               Rack
UN  192.168.1.11  68.09 KB   256          ?       53b41601-c145-4c1a-81d1-9b5f8b09ac73  rack1
UN  192.168.1.12  207.75 KB  256          ?       66642998-9179-4b06-b341-e654dc8e8ca6  rack1

service script

以下為 service script,儲存這個檔案到 /etc/init.d/cassandra,chmod 755 後就可以用 service cassandra start 啟動 cassandra。

#!/bin/bash
# chkconfig: 2345 99 01
# description: Cassandra

. /etc/rc.d/init.d/functions

CASSANDRA_HOME=/usr/share/apache-cassandra-2.2.3/
CASSANDRA_BIN=$CASSANDRA_HOME/bin/cassandra
CASSANDRA_NODETOOL=$CASSANDRA_HOME/bin/nodetool
CASSANDRA_LOG=$CASSANDRA_HOME/logs/cassandra.log
CASSANDRA_PID=/var/run/cassandra.pid
CASSANDRA_LOCK=/var/lock/subsys/cassandra
PROGRAM="cassandra"

if [ ! -f $CASSANDRA_BIN ]; then
  echo "File not found: $CASSANDRA_BIN"
  exit 1
fi

RETVAL=0

start() {
  if [ -f $CASSANDRA_PID ] && checkpid `cat $CASSANDRA_PID`; then
    echo "Cassandra is already running."
    exit 0
  fi
  echo -n $"Starting $PROGRAM: "
  daemon $CASSANDRA_BIN -p $CASSANDRA_PID >> $CASSANDRA_LOG 2>&1
  usleep 500000
  RETVAL=$?
  if [ $RETVAL -eq 0 ]; then
    touch $CASSANDRA_LOCK
    echo_success
  else
    echo_failure
  fi
  echo
  return $RETVAL
}

stop() {
  if [ ! -f $CASSANDRA_PID ]; then
    echo "Cassandra is already stopped."
    exit 0
  fi
  echo -n $"Stopping $PROGRAM: "
  $CASSANDRA_NODETOOL -h 127.0.0.1 decommission
  if kill `cat $CASSANDRA_PID`; then
    RETVAL=0
    rm -f $CASSANDRA_LOCK
    echo_success
  else
    RETVAL=1
    echo_failure
  fi
  echo
  [ $RETVAL = 0 ]
}

status_fn() {
  if [ -f $CASSANDRA_PID ] && checkpid `cat $CASSANDRA_PID`; then
    echo "Cassandra is running."
    exit 0
  else
    echo "Cassandra is stopped."
    exit 1
  fi
}

case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  status)
    status_fn
    ;;
  restart)
    stop
    start
    ;;
  *)
    echo $"Usage: $PROGRAM {start|stop|restart|status}"
    RETVAL=3
esac

exit $RETVAL

如何用 R 語言連接 cassandra 資料庫

以下簡述如何使用 R 語言連接 cassandra 資料庫。

  1. 調整 cassandra 設定,將 rpc server 打開,並重新啟動 cassandra

    修改 /usr/share/apache-cassandra-2.2.3/conf/cassandra.yaml,將 rpc server 打開

     start_rpc: true
    
  2. 下載 cassandra-jdbc library
    cassandra-jdbc 網頁,下載 cassandra-jdbc-2.1.1.jar 以及 cassandra-jdbc dependencies,將所有 jar 檔都放在要執行 R 語言的電腦的一個資料夾中。

  3. 在 R 語言,安裝 RJDBC 套件

     install.packages("RJDBC")
    
  4. R 語言的範例程式

    • 載入 RJDBC library

      > library(RJDBC)
      Loading required package: DBI
      Loading required package: rJava
      
    • 載入 Cassandra JDBC driver,以及相關 jars,我是放在 D:/git/system/pkg/cassandra/cassandra-jdbc/libs/ 這個目錄中,要注意目錄最後面的 libs 後面一定要加上 /

      > cassdrv <- JDBC("org.apache.cassandra.cql.jdbc.CassandraDriver", list.files("D:/git/system/pkg/cassandra/cassandra-jdbc/libs/",pattern="jar$",full.names=T))
      
    • 連接到 cassandra

      > casscon <- dbConnect(cassdrv, "jdbc:cassandra://192.168.1.11:9160/mykeyspace")
      
    • 對此 cassandra connection 執行 CQL

      > res <- dbGetQuery(casscon, "select * from users limit 10")
      
    • 取得 CQL 結果

      > res
      user_id fname lname
      1    1745  john smith
      2    1744  john   doe
      3    1746  john smith
      
  5. 錯誤訊息
    如果在連接 cassandra 時,發生 SQLNonTransientConnectionException,就表示 cassandra server 並沒有打開 rpc server 連接的設定。

     > casscon <- dbConnect(cassdrv, "jdbc:cassandra://192.168.1.11:9160/mykeyspace")
     Error in .jcall(drv@jdrv, "Ljava/sql/Connection;", "connect", as.character(url)[1],  : 
       java.sql.SQLNonTransientConnectionException: org.apache.thrift.transport.TTransportException: Cannot write to null outputStream
    

References

[研究] Apache Cassandra 2.0.3 安裝 (CentOS 6.5 x64)

設定 Cassandra cluster 的 token

cassandra token calculator