Cassandra – BMC Software | Blogs https://s7280.pcdn.co Mon, 11 Jan 2021 12:27:08 +0000 en-US hourly 1 https://s7280.pcdn.co/wp-content/uploads/2016/04/bmc_favicon-300x300-36x36.png Cassandra – BMC Software | Blogs https://s7280.pcdn.co 32 32 Cassandra Introduction: What is Apache Cassandra? https://s7280.pcdn.co/apache-cassandra-introduction/ Thu, 21 May 2020 15:44:26 +0000 https://www.bmc.com/blogs/?p=17453 To fully appreciate Apache Cassandra and what it can do, it’s helpful to first understand NoSQL databases and to then look more specifically at Cassandra’s architecture and capabilities. Doing so provides a good introduction to the system, so you can determine if it’s right for your business. (This article is part of our Cassandra Guide. […]]]>

To fully appreciate Apache Cassandra and what it can do, it’s helpful to first understand NoSQL databases and to then look more specifically at Cassandra’s architecture and capabilities. Doing so provides a good introduction to the system, so you can determine if it’s right for your business.

(This article is part of our Cassandra Guide. Use the right-hand menu to navigate.)

What is Cassandra?

Apache Cassandra is a distributed database management system that is built to handle large amounts of data across multiple data centers and the cloud. Key features include:

Written in Java, it’s a NoSQL database offering many things that other NoSQL and relational databases cannot.

Cassandra was originally developed at Facebook for their inbox search feature. Facebook open-sourced it in 2008, and Cassandra became part of the Apache Incubator in 2009. Since early 2010, it has been a top-level Apache project. It’s currently a key part of the Apache Software Foundation and can be used by anyone wanting to benefit from it.

Cassandra stands out among database systems and offers some advantages over other systems. Its ability to handle high volumes makes it particularly beneficial for major corporations. As a result, it’s currently being used by many large businesses including Apple, Facebook, Instagram, Uber, Spotify, Twitter, Cisco, Rackspace, eBay, and Netflix.

What is a NoSQL Database?

A NoSQL, often referred to as “not only SQL”, database is one that stores and retrieves data without requiring data to be stored in tabular format. Unlike relational databases, which require a tabular format, NoSQL databases allow for unstructured data. This type of database offers:

  • A simple design
  • Horizontal scaling
  • Extensive control over availability

NoSQL databases do not require fixed schema, allowing for easy replication. With its simple API, I like Cassandra for it’s overall consistentcy and its ability to handle large amounts of data.

That said, there are pros and cons of using this type of database. While NoSQL databases offer many benefits, they also have drawbacks. Generally, NoSQL databases:

  • Only support simply query language (SQL)
  • Are just “eventually consistent
  • Don’t support transactions

Nevertheless, they are effective with huge amounts of data and offer easy, horizontal scaling, making this type of system a good fit for many large businesses. Some ofthe most popular and effective NoSQL databases include:

  • Apache Cassandra
  • Apache HBase
  • MongoDB

What makes Apache Cassandra unique?

Cassandra is one of the most efficient and widely-used NoSQL databases. One of the key benefits of this system is that it offers highly-available service and no single point of failure. This is key for businesses that can afford to have their system go down or to lose data. With no single point of failure, it offers truly consistent access and availability.

Another key benefit of Cassandra is the massive volume of data that the system can handle. It can effectively and efficiently handle huge amounts of data across multiple servers. Plus, it is able to fast write huge amounts of data without affecting the read efficiency. Cassandra offers users “blazingly fast writes,” and the speed or accuracy is unaffected by large volumes of data. It is just as fast and as accurate for large volumes of data as it is for smaller volumes.

Another reason that so many enterprises utilize Cassandra is its horizontal scalability. Its structure allows users to meet sudden increases in demand, as it allows users to simply add more hardware to accommodate additional customers and data. This makes it easy to scale without shutdowns or major adjustments needed. Additionally, its linear scalability is one of the things that helps to maintain the system’s quick response time.

Some other benefits of Cassandra include:

  • Flexible data storage. Cassandra can handle structured, semi-structured, and unstructured data, giving users flexibility with data storage.
  • Flexible data distribution. Cassandra uses multiple data centers, which allows for easy data distribution wherever or whenever needed.
  • Supports ACID. The properties of ACID (atomicity, consistency, isolation, and durability) are supported by Cassandra.

Cleary, Apache Cassandra offers some discrete benefits that other NoSQL and relational databases cannot. With continuous availability, operational simplicity, easy data distribution across multiple data centers, and an ability to handle massive amounts of volume, it is the database of choice for many enterprises.

How does Cassandra work?

Apache Cassandra is a peer-to-peer system. Its distribution design is modeled on Amazon’s DynamoDB, and its data model is based on Google’s Big Table.

The basic architecture consists of a cluster of nodes, any and all of which can accept a read or write request. This is a key aspect of its architecture, as there are no master nodes. Instead, all nodes communicate equally.

While nodes are the specific location where data lives on a cluster, the cluster is the complete set of data centers where all data is stored for processing. Related nodes are grouped together in data centers. This type of structure is built for scalability and when additional space is needed, nodes can simply be added. The result is that the system is easy to expand, built for volume, and made to handle concurrent users across an entire system.

Its structure also allows for data protection. To help ensure data integrity, Cassandra has a commit log. This is a backup method and all data is written to the commit log to ensure data is not lost. The data is then indexed and written to a memtable. The memtable is simply a data structure in the memory where Cassandra writes. There is one active memtable per table.

When memtables reach their threshold, they are flushed on a disk and become immutable SSTables. More simply, this means that when the commit log is full, it triggers a flush where the contents of memtables are written to SSTables. The commit log is an important aspect of Cassandra’s architecture because it offers a failsafe method to protect data and to provide data integrity.

Who should use Cassandra?

If you need to store and manage large amounts of data across many servers, Cassandra could be a good solution for your business. It’s ideal for businesses who:

  • Can’t afford for data to be lost
  • Can’t have their database down due to the outage of a single server

Further, it’s also easy to use and easy to scale, making it ideal for businesses that are consistently growing.

At its core, Apache Cassandra’s structure is “built-for-scale” and can handle large amounts of data and concurrent users across a system. It lets major corporations store massive amounts of data in a decentralized system. Yet, despite the decentralization, it still allows users to have control and access to data.

And, data is always accessible. With no single point of failure, the system offers true continuous availability, avoiding downtime and data loss. Additionally, because it can be scaled by simply adding new nodes, there is constant uptime and no need to shut the system down to accommodate more customers or more data. Given these benefits, it’s not surprising that so many major companies utilize Apache Cassandra.

Related reading

]]>
Partition Key vs Composite Key vs Clustering Columns in Cassandra https://www.bmc.com/blogs/cassandra-clustering-columns-partition-composite-key/ Mon, 21 Jan 2019 00:00:37 +0000 https://www.bmc.com/blogs/?p=13451 Here we explain the differences between partition key, composite key and clustering key in Cassandra. In brief, each table requires a unique primary key. The first field listed is the partition key, since its hashed value is used to determine the node to store the data. If those fields are wrapped in parentheses then the […]]]>

Here we explain the differences between partition key, composite key and clustering key in Cassandra.

In brief, each table requires a unique primary key. The first field listed is the partition key, since its hashed value is used to determine the node to store the data. If those fields are wrapped in parentheses then the partition key is composite. Otherwise the first field is the partition key. Any fields listed after the partition key are called clustering columns. These store data in ascending or descending order within the partition for the fast retrieval of similar values. All the fields together are the primary key.

We discussed partitioning data here.

(This article is part of our Cassandra Guide. Use the right-hand menu to navigate.)

Clustering columns

Clustering columns determines the order of data in partitions.

What is the reason for having clustering columns? The whole point of a column-oriented database like Cassandra is to put adjacent data records next to each other for fast retrieval.

Remember than in a regular rdbms database, like Oracle, each row stores all values, including empty ones. But in a column oriented database one row can have columns (a,b,c) and another (a,b) or just (a). So if we are only interested in the value a then why not store that in the same data center, rack, or drive for fast retrieval? Remember that SQL select statements create subsets. So the column-oriented approach makes the prime data structure a type of subset.

This approach makes logical sense since we are usually only interested in a part of the data at any one time. For example why retrieve employee tax IDs, salary, manager’s name, when we just want their name and phone number?

Examples

Let’s look at books. The ISBN is a serial number of a book used by publishers. They are supposed to be unique. But let’s suppose they do not need to be for these examples.

Create a books keyspace, table, and put some data into it. (We discussed keyspaces here.)

Note that the primary key is PRIMARY KEY (isbn, author, publisher). In this case isbn is the partition key and author and publisher are clustering keys. It would make sense that in a collection of books you would want to store them by author and then publisher.

CREATE KEYSPACE books
       WITH REPLICATION = { 'class' : 'NetworkTopologyStrategy', 'datacenter1' : 1};

CREATE TABLE books (
   isbn text,
   title text,
   author text,
  publisher text,
   category text,
   PRIMARY KEY (isbn, author, publisher)
);

insert into books (isbn, title, author, publisher, category) values ('111', 'Fishing', 'Fred', 'Penguin Group', 'Sports');

insert into books (isbn, title, author, publisher, category) values ('111', 'Sailing', 'Sally', 'Penguin Group', 'Sports');

insert into books (isbn, title, author, publisher, category) values ('111', 'Archery', 'Fred', 'Penguin Group', 'Sports');

insert into books (isbn, title, author, publisher, category) values ('111', 'Boating', 'Joe', 'Penguin Group', 'Sports');

Notice that all of the values in the primary key must be unique, so it dropped one record because author Fred wrote and published more than one book with published Penguin Group.

Now select the partition key and the primary key. They are all the same since we want them all stored on the same virtual node.

select token(isbn), isbn from books;

 system.token(isbn)  | isbn
---------------------+------
 -175843201295106731 |  111
 -175843201295106731 |  111
 -175843201295106731 |  111

Now select all records and notices that the data is sorted by author and then publisher within the partition key 111.

select * from books;

 isbn | author | publisher     | category | title
------+--------+---------------+----------+---------
  111 |   Fred | Penguin Group |   Sports | Archery
  111 |    Joe | Penguin Group |   Sports | Boating
  111 |  Sally | Penguin Group |   Sports | Sailing

Now add another record but give it a different primary key value, which could result it in being stored in a different partition. What virtual node it is stored on depends on the token range assigned to the virtual node.

insert into books (isbn, title, author, publisher, category) values ('333', 'Trees', 'Charles Darwin', 'Hachette', 'Nature');


insert into books (isbn, title, author, publisher, category) values ('333', 'Trees', 'Charles Darwin', 'Amazon', 'Nature');

Observe again that the data is sorted on the cluster columns author and publisher. And the token is different for the 333 primary key value.

Recall that the partitioner has function configured in cassandra.yaml calculated the hash value and then distributes the data based upon partitioner. The default is org.apache.cassandra.dht.Murmur3Partitioner

select token(isbn), isbn, author, publisher from books;

 system.token(isbn)  | isbn | author         | publisher
---------------------+------+----------------+---------------
 -175843201295106731 |  111 |           Fred | Penguin Group
 -175843201295106731 |  111 |            Joe | Penguin Group
 -175843201295106731 |  111 |          Sally | Penguin Group
 7036029452358700311 |  333 | Charles Darwin |        Amazon
 7036029452358700311 |  333 | Charles Darwin |      Hachette

Composite Keys

This is just a table with more than one column used in the calculation of the partition key. We denote that with parentheses like this: PRIMARY KEY ((isbn, author), publisher). In this case isbn and author are the partition key and publisher is a clustering key.

drop table books;

CREATE TABLE books (
   isbn text,
   title text,
   author text,
  publisher text,
   category text,
   PRIMARY KEY ((isbn, author), publisher)
);

insert into books (isbn, title, author, publisher, category) values ('111', 'Fishing', 'Fred', 'Penguin Group', 'Sports');

insert into books (isbn, title, author, publisher, category) values ('111', 'Sailing', 'Sally', 'Penguin Group', 'Sports');

insert into books (isbn, title, author, publisher, category) values ('111', 'Archery', 'Fred', 'Penguin Group', 'Sports');

insert into books (isbn, title, author, publisher, category) values ('111', 'Boating', 'Joe', 'Penguin Group', 'Sports');

Now to show the partition key value we use the SQL token function and give it both the isbn and author values:

select token(isbn,author), isbn from books;

 system.token(isbn, author) | isbn
----------------------------+------
         725505645253967381 |  111
         960809148155353310 |  111
        5462216525918432145 |  111

Add the same data as above with the insert SQL statements. Notice that adding this data also drops one book because one author wrote more than one book with the same ISBN. By definition the primary key must be unique. That includes clustering columns, since they are part of the primary key. All we have changed with the compound key is the calculation of the partition key and thus where the data is stored.

select * from books;

 isbn | author | publisher     | category | title
------+--------+---------------+----------+---------
  111 |   Fred | Penguin Group |   Sports | Archery
  111 |    Joe | Penguin Group |   Sports | Boating
  111 |  Sally | Penguin Group |   Sports | Sailing
]]>
Using Tokens to Distribute Cassandra Data https://www.bmc.com/blogs/cassandra-tokens/ Wed, 16 Jan 2019 00:00:51 +0000 https://www.bmc.com/blogs/?p=13444 Cassandra distributes data based on tokens. A token is the hashed value of the primary key. When you add nodes to Cassandra you assign a token range to each node, or let Cassandra do that for you. Then when you add data to Cassandra it calculates the token and uses that to figure out on which server […]]]>

Cassandra distributes data based on tokens. A token is the hashed value of the primary key. When you add nodes to Cassandra you assign a token range to each node, or let Cassandra do that for you. Then when you add data to Cassandra it calculates the token and uses that to figure out on which server (node) to store the new data. That works fine at the start. But as we will see, it can result in one server having lots more data than the others, as your system grows and you add nodes to the ring (i.e., the collection of nodes), thus resulting in an imbalance in workload. So it is necessary to give thought to how this should be configured

(This article is part of our Cassandra Guide. Use the right-hand menu to navigate.)

How Cassandra Distributes Tokens

The algorithms that calculate the token are designed to range back and forth in such a way that data is distributed evenly. You can configure token/node assignment yourself in cassandra.yaml or you can let Cassandra take a best guess estimate.

To illustrate, suppose we have this table:

CREATE TABLE customers.customers (
    name text PRIMARY KEY,
    credit int
)

and these three records:

select token(name), name from customers.customers;

 system.token(name)   | name
----------------------+----------------
 -1595003126634288162 |     Book Store
  2201572791825907709 |      Bok Store
  6005990370378710037 | Hardware Store

We can see where each of this records are stored by using the nodetool command and showing the token with the system.token() CQL command. The format for nodetool is nodetool getendpoints keyspace table token.

As we can see from the ip addresses below, in our cluster of two servers the records are distributed across both.

nodetool getendpoints customers customers -1595003126634288162
172.31.47.43
nodetool getendpoints customers customers 2201572791825907709
172.31.46.15
nodetool getendpoints customers customers 6005990370378710037
172.31.47.43

The Problem with Uneven Data Distribution

Now, if you stop and think about this, that works fine when you first set up your cluster. But as your system grows Cassandra can pile up data on one node and leave others underutilized. Plus there is the problem of how to move existing data onto new nodes. So what do you do?

There are three different algorithms you can use to assign tokens to nodes. Murmur3Partitioner in cassandra.yaml lets you set allocate_tokens_for_keyspace. You can use that with num_tokens to override the random distribution of tokens (meaning the other partitioner algorithms). This will let new nodes take more of the data from existing nodes thus reducing the over/under utilisation problem. It does this by letting the assignment of ranges to nodes shift dynamically based upon data load in the other nodes. But since it does not move existing data over to the new nodes will take some time for the data to be spread move evenly.

num_tokens means the division of a node into virtual node. The default is 256.

In the next post we will explain in more detail this algorithm so you can figure out how to tune this for your environment.

]]>
Configuring Apache Cassandra Data Consistency https://www.bmc.com/blogs/configuring-apache-cassandra-data-consistency/ Mon, 07 Jan 2019 00:00:19 +0000 https://www.bmc.com/blogs/?p=13400 Let’s look at how Apache Cassandra handles data consistency. If you write data to n – 1 nodes in a cluster and then an application reads it from node n Cassandra could report that the data is not there as replication is not instant. That could be a big problem or not a problem at […]]]>

Let’s look at how Apache Cassandra handles data consistency.

If you write data to n – 1 nodes in a cluster and then an application reads it from node n Cassandra could report that the data is not there as replication is not instant. That could be a big problem or not a problem at all. It depends on the application. If it’s a revenue generating application then it’s a problem.

So, Cassandra lets administrators configure data replication and consistency at the application level. The trade off is response time versus data accuracy.

This ability to configure this at the application level is called eventual consistency. As the name implies you can tell Cassandra to wait after an operation to write all data to all data centers and racks or move to the next operation after the first write is done with the understanding that Cassandra will eventually catch up.

This idea is the same as determining what kind of storage to rent or buy when designing an application. Applications that are deemed less mission critical might use lower cost storage and even fewer drives and make fewer replicas or no replicas at all than mission critical ones.

Consistency can be set at these levels:

  • data center
  • cluster
  • I/O operation type (i.e., read or write)

(This article is part of our Cassandra Guide. Use the right-hand menu to navigate.)

Write and Read Consistency

Write consistency has lots of different options. Here are a couple.

ALL Data must be written to the memtable and commit log on each node. The steps that Cassandra goes through as it writes data is to:

  • write data to the memtable (memory)
  • write to the commit log
  • write to disk
  • compact the data
QUORUM A quorum at the data center level.  A quorum is ((number of replicas )) / 2 + 1 rounded up.  Adding 1 makes this number the next integer when that division results in a fraction.  And you cannot write to a fraction of a data center, so add one more
ONE, TWO, THREE 1, 2, or 3 replicate, meaning at the node level.

Read Consistency

Depending on the write consistency set, some nodes will have older copies of data than others. So it makes sense that you can configure the read consistency as well.

ALL Waits until all replicas have responded.
etc.

Replication Strategy

Replication is a factor in data consistency. A replica means a copy of the data.

in order to whether a write has been successful, and whether replication is working, Cassandra has an object called a snitch, which determines which datacenter and rack nodes belong to and the network topology.

There are two replication stations:

  1. SimpleStrategy—one datacenter and one rack.
  2. NetworkTopologyStrategy—multiple racks and multiple data centers. This is preferred even when there is only one data center.

Example

Here we illustrate with an example.

First follow these instructions to set up a cluster.

Use nodetool to determine the name of the data center as reported by the snitch. Here the name is datacenter1. This shows that there are two nodes in this cluster. Of courses you would run this on each node to see what data center each node belongs to.

nodetool status

Datacenter: datacenter1
=======================
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
--  Address       Load       Tokens       Owns    Host ID                               Rack
UN  172.31.46.15  532.22 MiB  256          ?       58999e76-cf3e-4791-8072-9257d334d945  rack1
UN  172.31.47.43  532.59 MiB  256          ?       472fd4f0-9bb3-48a3-a933-9c9b07f7a9f6  rack1

Create a keyspace with NetworkTopologyStrategy with 1 replica to datacenter1. So that means write the data to two racks, since there is only one data center.

CREATE KEYSPACE Customers
       WITH REPLICATION = { 'class' : 'NetworkTopologyStrategy', 'datacenter1' : 1};

Now create a table:

CREATE TABLE  Customers.Customers (      
Name text PRIMARY KEY,  
credit int 
);

Put some data in it:

insert into Customers.Customers (name, credit) values ('Hardware Store', 1000);

Turn tracing on.

cqlsh> TRACING on;
Now Tracing is enabled

And write another record:

insert into Customers.Customers (name, credit) values ('Book Store', 1000);

Cassandra responds with some information on latency. It does not show rack level operations.

Tracing session: bf8e0a90-0c43-11e9-9628-9d6a90b241c5

Parsing insert into Customers.Customers (name, credit) values ('Book Store', 1000); 

activity| timestamp | source | source_elapsed | client

[Native-Transport-Requests-1] | 2018-12-30 15:01:12.761000 | 172.31.46.15 |  203 | 127.0.0.1

Preparing statement [Native-Transport-Requests-1] | 2018-12-30 15:01:12.762000 | 172.31.46.15 | 359 | 127.0.0.1

Determining replicas for mutation [Native-Transport-Requests-1] | 2018-12-30 15:01:12.762000 | 172.31.46.15 |            662 | 127.0.0.1

Appending to commitlog [Native-Transport-Requests-1] | 2018-12-30 15:01:12.762000 | 172.31.46.15 | 753 | 127.0.0.1

Adding to customers memtable [Native-Transport-Requests-1] | 2018-12-30 15:01:12.762000 | 172.31.46.15 |            827 | 127.0.0.1

Request complete | 2018-12-30 15:01:12.762121 | 172.31.46.15 | 1121 | 127.0.0.1
]]>
Using JSON with Cassandra https://www.bmc.com/blogs/using-json-with-cassandra/ Wed, 02 Jan 2019 00:00:08 +0000 https://www.bmc.com/blogs/?p=13393 Cassandra provides support for JSON. You can, of course, store JSON text into Cassandra text columns. But that is not what we mean here. Here we mean you can use JSON to write to Cassandra tables. We illustrate with an example. First create a keyspace. create keyspace json with REPLICATION = {'class' : 'SimpleStrategy', 'replication_factor' […]]]>

Cassandra provides support for JSON. You can, of course, store JSON text into Cassandra text columns. But that is not what we mean here. Here we mean you can use JSON to write to Cassandra tables.

We illustrate with an example. First create a keyspace.

create keyspace json with REPLICATION = {'class' : 'SimpleStrategy', 'replication_factor' : 2 };

(This article is part of our Cassandra Guide. Use the right-hand menu to navigate.)

Simple JSON Example

Let’s make a table with three columns. Then write data into it using the JSON keyword. That tells Cassandra to maps the JSON values to the columns names, just as you would expect with JSON.

create table books (isbn text primary key, title text, publisher text);

insert into books JSON '{"isbn": "123", 
"title": "The Magic Mountain",
 "publisher": "Knofp"}';

Then we list the data. It looks like regular columnar data and not JSON. Because it’s just regular data. We simply used JSON to add it, which is useful since data is often represented as JSON.

select * from books;

 isbn | publisher | title
------+-----------+--------------------
  123 |     Knofp | The Magic Mountain

Nested JSON

Here is a more complicated example. We have a customer record with a sales type that is of type list. Obviously a customer would have multiple sales. So this is a good way to represent that.

First we create the sale type. Then we create the customers table. We have to use the FROZEN keyword as each sales transaction cannot be changed, i.e., it is immutable. If you want to change a sales transaction you would have to delete it and then add it back.

use json;

CREATE type json.sale ( id int, item text, amount int );

CREATE TABLE json.customers ( id int  PRIMARY KEY, name text, balance int, sales list> );

Now add values. Since the sales items are a list we can add more than one.

INSERT INTO json.customers (id, name, balance, sales) 
VALUES (123, 'Greenville Hardware', 700,
 [{ id: 5544, item : 'tape', amount : 100},
  { id: 5545, item : 'wire', amount : 200}]) ;

Now list the items. Note that there is no question mark around the key value in the jSON. This is because it is a JSON object.

select * from customers;

 id  | balance | name                | sales
-----+---------+---------------------+--------------------------------------------------------------------------------
 123 |     700 | Greenville Hardware | [{id: 5544, item: 'tape', amount: 100}, {id: 5545, item: 'wire', amount: 200}]

If you want to convert it to a JSON string then use toJson()

select id, toJson(sales) from customers;

 id  | system.tojson(sales)
-----+--------------------------------------------------------------------------------------------
 123 | [{"id": 5544, "item": "tape", "amount": 100}, {"id": 5545, "item": "wire", "amount": 200}]
]]>
Stress Testing and Performance Tuning Apache Cassandra https://www.bmc.com/blogs/stress-testing-and-performance-tuning-apache-cassandra/ Thu, 20 Dec 2018 00:00:41 +0000 https://www.bmc.com/blogs/?p=13254 Here we show how to stress test a Cassandra cluster using the cassandra-stress tool. What this tool does is run inserts and queries against a table that it generates by itself or an existing table or tables. (This article is part of our Cassandra Guide. Use the right-hand menu to navigate.) The Basic Flow The […]]]>

Here we show how to stress test a Cassandra cluster using the cassandra-stress tool.

What this tool does is run inserts and queries against a table that it generates by itself or an existing table or tables.

(This article is part of our Cassandra Guide. Use the right-hand menu to navigate.)

The Basic Flow

The test works like this:

  • Insert random data. You specify the length of text fields or random numeric values by selecting a fixed value or a statistical distribution such as a normal, uniform, or other distribution. The normal distribution are values drawn from some mean and standard deviation, i.e. the familiar bell curve. The uniform distribution is random numbers drawn from a range like 1,2,3,….
  • Run select statements using the values generated.
  • Calculate the time in milliseconds to run each operation.
  • Calculate the mean time, standard deviations number of garbage collections etc. for each iteration. This gives you an average and the bell curve so you can see how widely your operations are disbursed. It gives you graphs over time so you can see whether performance degrades over time. Lots of operations far from the mean indicate a high level of variance. This could point to items you need to tune, such as indexes, partitions, add more memory, etc.

Test Setup

You need a Cassandra cluster. If you do not have one yet follow these instructions.

We need to create a keyspace, table, and index and to create a stress test configuration file in YAML format.

Now deactivate Python 2.7 virtual environment, if you are using that, then run cqlsh. Paste in the following Cassandra SQL.

CREATE KEYSPACE Library
WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 3 };

CREATE TABLE Library.book (
ISBN text,
copy int,
title text,
PRIMARY KEY (ISBN, copy)
);

create index on library.book (title);

Now, create a text file named stress-books.yaml and paste the following into it. This is a YAML format, so don’t mess up the indentation.

Below we explain the fields.

keyspace: library

table: book

columnspec:
  - name: text
    size: uniform(5..10) 
    population: uniform(1..10) 
  - name: copy
    cluster: uniform(20..500) 
  - name: title
    size: uniform(5..10)

insert:
  partitions: fixed(1) 
  select: fixed(1)/500 
  batchtype: UNLOGGED         

queries:
   books:
      cql: select *  from book where title = ?
      fields: samerow

The field names are:

keyspace Name of existing keyspace. You could also put SQL here to create one if it does not exist.
table Name of existing table. You could also put SQL here to create one if it does not exist.
insert, queries These are the functions we will call. The insert does the insert and the queries/books does the query we put there. It runs queries against the values inserted in the batch it just ran.
columnspec:
– name: text
size: uniform(5..10)
There is one columnspec for each value we want to populate. The size is the length of the field. uniform(5..10) means to generate a text string from 5 to10 characters. If it was a numeric field it would create random numbers in that range.
insert:
partitions: fixed(1)
select: fixed(1)/500
batchtype: UNLOGGED
This means to insert a fixed number of rows in each partition in each batch. We explained batch operations here.

Run the Stress Test

Run the command below to start the test. The arguments are:

cassandra-stress user profile=stress-books.yaml ops\(insert=1,books=1\) n=10000  -graph file=stress.html
user profile=stress-books.yaml means use stress-books.yaml for instructions.
n=10000
ops\(insert=1,books=1\)
Here we say run 10,000 batches and for each run the insert code 1 time and the books code 1 time. If you leave this off it will run until the standard deviation of the error is < 0.2.
-graph file=stress.html This will create an html file called stress.html that will graph the results of different metrics.

The output is quite long. Here is part of it truncated.

******************** Stress Settings ********************
Command:
Type: user
Count: 10,000


…

Connected to cluster: Walker Cluster, max pending requests per connection 128, max connections per host 8
Datatacenter: datacenter1; Host: localhost/127.0.0.1; Rack: rack1
Generating batches with [1..1] partitions and [0..1] rows (of [20..500] total rows in the partitions)

Sleeping 2s...
Warming up insert with 500 iterations...
Warming up books with 500 iterations...
Thread count was not specified

It will echo metrics for each batch iteration. You can copy and paste this test and then import it into Excel or Google Sheets to make that easier to read.

type       total ops,    op/s,    pk/s,   row/s,    mean,     med,     .95,     .99,    .999,     max,   time,   stderr, errors,  gc: #,  max ms,  sum ms,  sdv ms,      mb
books,          1003,    1003,     383,     387,     5.0,     3.9,    12.5,    20.2,    29.7,    40.7,    1.0,  0.00000,      0,      2,      10,      18,       1,     319
insert,          825,     825,     825,     934,     2.7,     2.0,     7.3,    12.1,    16.9,    23.8,    1.0,  0.00000,      0,      2,      10,      18,       1,     319
total,          1828,    1828,    1208,    1321,     4.0,     2.9,    11.1,    18.1,    27.2,    40.7,    1.0,  0.00000,      0,      2,      10,      18,       1,     319
books,          1096,     930,     350,     360,     5.8,     3.9,    14.1,    27.4,    33.3,    33.3,    1.1,  0.11339,      0,      0,       0,       0,       0,       0
insert,          904,     790,     790,     910,     3.0,     2.3,     9.0,    12.1,    12.3,    12.3,    1.1,  0.11339,      0,      0,       0,       0,       0,       0
total,          2000,    1720,    1140,    1270,     4.5,     3.2,    11.9,    21.9,    33.3,    33.3,    1.1,  0.11339,      0,      0,       0,       0,       0,       0

Do that and then the spreadsheet is easier to read.

This shows the total numbers of inserts and selects (books is what we named that) and the mean (average) number of milliseconds required to do that. In this example I ran earlier it ran 2,000 times.

A statistician looking at this would want to know 2, 3, and 4 standard deviations from the mean. That corresponds to 95%, 99%, and 99.9% of the transactions. In other words those are far from the mean.

Below is the right-hand side of the spreadsheet. Not all the metrics can fit onto this screen, such as number of garbage collections (the number of times that the Java Virtual Machine had to clear its cache. When it does that all operations pause.) But this does not matter as the HTML file will give the complete picture.

Open the file stress.html with a browser.

You can see that the test took 22 seconds running on my 2 cluster t2.large Amazon Ubuntu machines. The spikes in operation time coincided with garbage collections. You can see that by selecting the gc# option in the graph type drop down.

The stats show that the average throughout was 2,231 inserts per second.

You can pick from the drop down at the top right of the chart to plot different metrics.

 

]]>
Cassandra SQL Batches and Maps https://www.bmc.com/blogs/cassandra-sql-batches-and-maps/ Wed, 12 Dec 2018 00:00:20 +0000 https://www.bmc.com/blogs/?p=13195 There are too many SQL commands and data types to look at all of them in one blog post, so we will look at a few here. In order the understand the examples below you should have some understanding of regular, i.e., Oracle or other RDBMS, SQL, as Cassandra SQL is almost the same. And […]]]>

There are too many SQL commands and data types to look at all of them in one blog post, so we will look at a few here.

In order the understand the examples below you should have some understanding of regular, i.e., Oracle or other RDBMS, SQL, as Cassandra SQL is almost the same. And to get started with Cassandra, you can read what wrote here. Look at that even if you already know and have installed Cassandra so that you can the SQL from there to set up a table and index that we will start with here.

(This article is part of our Cassandra Guide. Use the right-hand menu to navigate.)

Cassandra SQL Shell

First step, to open the Cassandra SQL command line enter: cqlsh.

Paste in the SQL below. If you looked at that other blog post you will have some data here.

select * from Library.book;

Here is another query.

(Note that Cassandra requires the use of single and not double quotes, or you will get the error no viable alternative at input.)

select ssn from Library.patron where checkedOut contains '1234';

Collections, Maps, and Sets

Cassandra supports complex data types including user-defined objects, collections, maps, and sets.

For example. if we type:

describe library.patron;

We can see that commands that were used to create the table. Below is a truncated view of that as the complete view shows lots of system administration type options, which we will look at in another post.

Below you can see that the column checkedout is a set of type text. A set is a collection of unique values.

CREATE TABLE library.patron (
ssn int PRIMARY KEY,
checkedout set<text>
)

Maps

Maps store values in {key->value} format.

First create this keyspace.

CREATE KEYSPACE shopping
WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 3 };

Then create a shopping cart for an ecommerce app where the items purchased are a map. The first field is the customer order number. The second is the combination of what they bought and how much, e.g, {“shoes”, 1}.

CREATE TABLE shopping.cart (
customerOrder int PRIMARY KEY,
items map<text,int>
);

Add some data, i.e., make a sale:

INSERT INTO shopping.cart (customerOrder, items) 
VALUES (
  1,
 {'toys' : 12, 'socks': 5});

And list it:

select * from shopping.cart;
customerorder | items
---------------+--------------------------
1 | {'socks': 5, 'toys': 12}

Batches

With an ecommerce application you would want to use batches.

Batches ensure atomicity, which RDBMS programmers would say ensure referential integrity. This ensures that if any of the SQL statements in a batch have an error then none of the statements are applied.

That’s import for, for example, a shopping cart app. We would only want to update the inventory if the sales transaction worked.

To illustrate that first create an inventory table and put an item into it:

CREATE TABLE shopping.inventory (
      item text PRIMARY KEY,
      quantity int
);

INSERT INTO shopping.inventory (item, quantity) VALUES ('eggs', 48);

Now make a sale of 4 eggs in a BATCH:

BEGIN BATCH

INSERT INTO shopping.cart (customerOrder, items) 
VALUES (
2,
{'eggs' : 4}
);

UPDATE shopping.inventory
SET quantity = 44
where item = 'eggs';

APPLY BATCH;
]]>
How to Setup a Cassandra Cluster https://www.bmc.com/blogs/setup-cassandra-cluster/ Thu, 06 Dec 2018 00:00:05 +0000 https://www.bmc.com/blogs/?p=13165 Here we show how to set up a Cassandra cluster. We will use two machines, 172.31.47.43 and 172.31.46.15. First, open these firewall ports on both: 7000 7001 7199 9042 9160 9142 Then follow this document to install Cassandra and get familiar with its basic concepts. Make sure to install Cassandra on each node. (This article […]]]>

Here we show how to set up a Cassandra cluster. We will use two machines, 172.31.47.43 and 172.31.46.15. First, open these firewall ports on both:

7000
7001
7199
9042
9160
9142

Then follow this document to install Cassandra and get familiar with its basic concepts. Make sure to install Cassandra on each node.

(This article is part of our Cassandra Guide. Use the right-hand menu to navigate.)

Configure Cluster Setting

There is no central master in a Cassandra cluster. Instead you just make each one aware of the others and they work together.

First we will edit /etc/cassandra/cassandra.yaml on both machines set the the values as shown in the table below. Don’t change the cluster name yet. We will do that later.

    • seeds—set the IP address on one machine to be the seed. It is not necessary that all machines be seeds. Seeds are nodes that Cassandra nodes use when you start Cassandra start to find other nodes.
    • listen_address—the IP address for Cassandra to run.
    • endpoint_snitch—this is used to determine where to route data and send replicas. We use the default below. There are several. The others are rack-aware, meaning they would not put a replica on the same physical storage rack as another. If you did that and the whole rack failed the data could be lost. There is even one (Ec2Snitch) designed for Amazon EC2 that can spread data across Amazon Zones.
machine 172.31.46.15 settings machine 172.31.47.43 settings
endpoint_snitch: SimpleSnitch

- seeds: "seeds: 172.31.47.43"

listen_address: 172.31.46.15
endpoint_snitch: SimpleSnitch

- seeds: "seeds: 172.31.47.43"

listen_address: 172.31.47.43

Now run on both machines:

sudo service cassandra start

Then wait a few seconds for discovery to work and then run on both machines:

nodetool status

It should show both nodes:

Datacenter: datacenter1
=======================
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
--  Address       Load       Tokens       Owns (effective)  Host ID                               Rack
UN  172.31.46.15  245.99 KiB  256          100.0%            fb1d89bb-cbe2-488f-b2e7-da145bd2dde7  rack1
UN  172.31.47.43  196.01 KiB  256          100.0%            472fd4f0-9bb3-48a3-a933-9c9b07f7a9f6  rack1

If you get any kind of error message look in /var/log/cassandra/system.log

Now let’s change the name of the cluster from the defaut. Run cqlsh and then paste in the SQL below. Cassandra does not replicate this system change across the cluster so you have to run this on both machines.

UPDATE system.local SET cluster_name = 'Walker Cluster' where key='local';

Now edit /etc/cassandra/cassandra.yaml and change the cluster name to whatever you want. It should be the same on both machines:

cluster_name: 'Walker Cluster'

Then:

sudo service cassandra restart

Run this check again:

nodetool status 

Datacenter: datacenter1
=======================
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
--  Address       Load       Tokens       Owns (effective)  Host ID                               Rack
UN  172.31.46.15  312.4 KiB  256          100.0%            fb1d89bb-cbe2-488f-b2e7-da145bd2dde7  rack1
UN  172.31.47.43  294.71 KiB  256          100.0%            472fd4f0-9bb3-48a3-a933-9c9b07f7a9f6  rack1

Now, following these instructions from our introduction to cassandra, let’s create some data. We will see that data entered on one node is replicated to another. Paste these SQL commands into csql:

 CREATE KEYSPACE Library
      WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 3 };


CREATE TABLE Library.book (       
ISBN text, 
copy int, 
title text,  
PRIMARY KEY (ISBN, copy)
 );

CREATE TABLE  Library.patron (      
ssn int PRIMARY KEY,  
checkedOut set 
);


INSERT INTO  Library.book (ISBN, copy, title) VALUES('1234',1, 'Bible');
INSERT INTO  Library.book (ISBN, copy, title) VALUES('1234',2, 'Bible');
INSERT INTO  Library.book (ISBN, copy, title) VALUES('1234',3, 'Bible');
INSERT INTO  Library.book (ISBN, copy, title) VALUES('5678',1, 'Koran');
INSERT INTO  Library.book (ISBN, copy, title) VALUES('5678',2, 'Koran');

Then logon to the opposite machine and verify that the data has been copied there:

select * from Library.book;

 isbn | copy | title
------+------+-------
 5678 |    1 | Koran
 5678 |    2 | Koran
 1234 |    1 | Bible
 1234 |    2 | Bible
 1234 |    3 | Bible

]]>