Apache Cassandra is a key member of the NoSQL ecosystem. Because Cassandra uses a decentralized architecture (similar to memcached), setting up a cluster is straightforward. Below is a brief guide on building a cluster using Cassandra 0.7.
1. Basic Configuration
First, prepare three or more computers. Assume we have three Linux machines with IP addresses 192.168.0.100, 192.168.0.101, and 192.168.0.102. Ensure the Java Runtime Environment (JRE) is installed, then download here the binary distribution package for version 0.7.
Select one machine to start the configuration by extracting the Cassandra package:
$ tar -zxvf apache-cassandra-$VERSION.tar.gz
$ cd apache-cassandra-$VERSION
The main configuration file is conf/cassandra.yaml. Starting from version 0.7, XML configuration files are no longer used. If you are unfamiliar with YAML format, it is recommended to learn about it here first.
Cassandra defines several default directories in its configuration file:
data_file_directories: /var/lib/cassandra/data
commitlog_directory: /var/lib/cassandra/commitlog
saved_caches_directory: /var/lib/cassandra/saved_caches
You can specify multiple directories for data_file_directories; Cassandra will automatically synchronize data across all of them. Additionally, the log4j-server.properties file has a default directory for log files:
log4j.appender.R.File=/var/log/cassandra/system.log
Generally, the default configuration is sufficient unless you have specific storage requirements. You have two options: either create the necessary directories according to the defaults, or modify the configuration file to use custom directories.
For simplicity, we will proceed with the first option:
$ sudo mkdir -p /var/log/cassandra
$ sudo chown -R `whoami` /var/log/cassandra
$ sudo mkdir -p /var/lib/cassandra
$ sudo chown -R `whoami` /var/lib/cassandra
The command `whoami` is a Linux utility that returns the current logged-in username. If you do not intend to run Cassandra under the current user, replace `whoami` with the specific username.
2. Cluster Configuration
Since Cassandra uses a decentralized structure, when a node starts, it needs a way to notify the existing cluster of its presence. The configuration file includes a ‘seeds’ setting. Seeds refer to one or more machines that can contact all nodes in the cluster. If all nodes are located in the same data center and subnet, simply select a few stable machines. In this example with only three machines, we choose the first one as the seed node:
seeds:
- 192.168.0.100
Next, configure the IP address for inter-node communication:
listen_address: 192.168.0.100
Note that you must use a specific IP address here; addresses like 0.0.0.0 cannot be used.
Configure the IP address for Thrift client (application) access:
rpc_address: 192.168.0.100
This setting can use 0.0.0.0 to listen on all network interfaces of the machine.
Keyspaces and ColumnFamilies in Cassandra do not require pre-configuration; they are created and maintained at runtime.
Copy the configured Cassandra installation to the second and third machines, create the corresponding directories, and update listen_address and rpc_address to reflect the actual IP addresses of those machines. All configurations are now complete.
3. Starting Cassandra Nodes and Cluster Management
The startup order does not matter, provided that the seed node is started first:
$ bin/cassandra -f
The -f flag runs Cassandra in the foreground, which is useful for debugging and observing log messages. In production environments, this parameter is typically omitted so that Cassandra runs as a daemon.
Once all nodes are running, you can manage the cluster using the bin/nodetool utility. For example, to view the status of all nodes:
$ bin/nodetool -host 192.168.0.101 ring
The output resembles the following:
Address Status State Load Owns Token 159559... 192.168.0.100 Up Normal 49.27 KB 39.32% 563215... 192.168.0.101 Up Normal 54.42 KB 16.81% 849292... 192.168.0.102 Up Normal 73.14 KB 43.86% 159559...
The -host parameter specifies which node nodetool communicates with. For the ring command, it does not matter which node you choose, so you can specify any one of them.
From the output, you can see if nodes are online, their state, data load, and token (which acts as a unique identifier generated automatically upon the node’s first startup). You can use nodetool combined with tokens to manage specific nodes. For example, to view detailed information about a specific node:
$ bin/nodetool -host 192.168.0.101 info
The result looks similar to this:
84929280487220726989221251643883950871 Load : 54.42 KB Generation No : 1302057702 Uptime (seconds) : 591 Heap Memory (MB) : 212.14 / 1877.63
To view the data structure information of a specific node:
$ bin/nodetool -host 192.168.0.101 cfstats
Output:
Keyspace: Keyspace1 Read Count: 0 Write Count: 0 Pending Tasks: 0 Column Family: CF1 SSTable count: 1
To remove an offline node (e.g., if the second machine is shut down or broken):
$ bin/nodetool -host 192.168.0.101 removetoken 84929280487220726989221251643883950871
To bring an offline node back online, simply start the Cassandra program; it will automatically rejoin the cluster.
In practice, you may need to back up data periodically by creating a snapshot. This operation is very simple in Cassandra:
$ bin/nodetool -host 192.168.0.101 snapshot
4. Testing Data Read and Write
Using client components with unit tests is the preferred approach. However, if you just want to verify that the cluster can read and write data correctly, you can perform a simple test using cassandra-cli:
$ bin/cassandra-cli -host 192.168.0.101
Then enter the following commands:
create keyspace Keyspace1; use Keyspace1; create column family Users with comparator=UTF8Type and default_validation_class=UTF8Type; set Users[jsmith][first] = 'John'; set Users[jsmith][last] = 'Smith'; get Users[jsmith];
The above commands create a keyspace named “Keyspace1”, a Column Family named “Users”, and add an item to Users. Normally, you should see output similar to:
=> (column=first, value=John, timestamp=1302059332540000) => (column=last, value=Smith, timestamp=1300874233834000) Returned 2 results.