Cassandra Durability Test

29 Nov 2015

This is a test of Cassandra's out-of-the-box durability capabilities, also run on my laptop, the same as with PostgreSQL, above. Here, I use the default binary release of Cassandra 3.0.0 (not any distro-specific packages), unpacked in my home directory.

In your regular user's directory, create this bash script, kill-cass.sh, that will find and kill -9 your Java Cassandra process:

#!/bin/bash

set -u
set -e
set -o pipefail

# WARNING: this only works when there is just one cassandra node running

CASSPID=$(ps -ef | grep CassandraDaemon | grep -v grep | awk '{ print $2 }')
kill -9 ${CASSPID}

In your regular user's go/src directory, (such as ${HOME}/go/src/github.com/foo/cass-durability/insert-ints), create this main.go file:

package main

import (
	"fmt"
	"os"

	"github.com/gocql/gocql"
)

func main() {
	cluster := gocql.NewCluster("127.0.0.1")
	cluster.ProtoVersion = 4 // have to do this for Cass 3
	cluster.Keyspace = "foo"
	session, err := cluster.CreateSession()
	if err != nil {
		fmt.Fprintf(os.Stderr, "Unable to connect to cluster: %v\n", err)
		os.Exit(1)
	}

	i := 0
	for {
		i++
		err = session.Query("insert into t (i) values (?)", i).Exec()
		if err != nil {
			fmt.Fprintf(os.Stderr, "Did not insert %d\n", i)
			os.Exit(1)
		}
		fmt.Printf("inserted %d\n", i)
	}
	defer session.Close()
}

Build the above go file like so:

$ cd go/src/github.com/manniwood/pg-play/insert-ints
$ go get github.com/gocql/gocql
$ go build

In a root terminal, turn off your hard drive's write caching, using the same set-write-through.sh script we wrote for the PostgreSQL durability test, above:

# ./set-write-through.sh

In the first user terminal, start running Cassandra, in the foreground:

$ cd ${HOME}/apache-cassandra-3.0.0/bin
$ ./cassandra -f

In a second user terminal, create the table we will use (and drop it if it exists from a prior test:

$ cd ${HOME}/apache-cassandra-3.0.0/bin
$ ./cqlsh -e "create keyspace foo with replication = {'class':'SimpleStrategy', 'replication_factor':1};"

$ ./cqlsh -k foo -e "drop table t;"
$ ./cqlsh -k foo -e "create table t (i int primary key);"

In a third user terminal, launch the insert-ints go program:

$ ./insert-ints

In a fourth user terminal, kill Cassandra:

$ ./kill-cass.sh

Back in your third user terminal, the go program should have stopped, like so:

...
inserted 3093
inserted 3094
inserted 3095
inserted 3096
inserted 3097
inserted 3098
Did not insert 3099

In your first user terminal, start cassandra back up:

$ ./cassandra -f -p ${HOME}/apache-cassandra-3.0.0/cass.pid

In second user terminal, look to see how many writes were successfully persisted to disk:

$ ./cqlsh -k foo -e "select count(*) from t;"

 count
-------
  1825

(1 rows)

$ ./cqlsh -k foo -e "select max(i) from t;"

 system.max(i)
---------------
          1825

(1 rows)

Out of the box, Cassandra does not emphasize durability.