Wednesday, March 30, 2016

Cassandra Performance Tuning

Dedicated Commit Log Disk: I think this is the first tune-up you may want to try as it gives you a significant performance improvement. But before changing commit log destination it would be better to know it gives performance boost. Cassandra write operations are occurred on a commit log on disk and then to an in-memory table structure called Memtable. When thresholds are reached, that Memtable is flushed to a disk in a format called SSTable. So if you separate out Commit Log locations, it will isolate Commit Log I/O traffics from other Cassandra Reads, Memtables and SSTables traffics. Remember, after the flush, the Commit Log is no longer needed and is deleted. So the Commit Log disk doesn't need to be large. It just need to be in the size where it can holds Memtable data before its flushed. You can follow the following steps to change commit log location for Cassandra.

Step#1: Mount a separate partition for commit log
root@ip-10-0-0-24:[/root]
$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 124G 78G 40G 67% /
/dev/sda2 50G 2G 46G 1% /mnt/commitlog
none 3.8G 1007M 2.8G 27% /dev/shm
Step#2: Make sure you give expected ownership and access on that drive
root@ip-10-0-0-24:[/root]
$ chown cassandra:cassandra /mnt/commitlog
root@ip-10-0-0-24:[/root]
$ chmod 755 /mnt/commitlog
Step#3: Edit Cassandra configuration file which can be found at conf/cassandra.yaml. You will find a property "CommitLogDirectory", update it based on your mount location. For my case, it will be:
CommitLogDirectory: /mnt/commitlog
Step#4: Restart your Cassandra cluster.


Increasing Java Heap Size: Cassandra runs on JVM. So you might face out of memory issues when you run a heavy load on Cassandra. There is also a rule of thumb about how you want to keep your heap size.
  • Heap Size = 1/2 of System Memory when System Memory < 2GB
  • Heap Size = 1GB when System Memory >= 2GB and <= 4GB
  • Heap Size = 1/4 of System Memory(but not more than 8GB) when System Memory >4GB
Remember, just a larger heap size might not give you a performance boost. So a well-tuned Java heap size is very important. To change the Java heap size, you need to update cassandra-env.sh file and then restart Cassandra cluster again. If you are using Opscenter, you should see the updated heap size on one of the Opscenter's metrics.


Tune Concurrent Reads and Writes: Staged Event-Driven Architecture(SEDA) is used for implementing Cassandra. It breaks the application into stages. Concurrent readers and writers control the maximum number of threads allocated to a particular stage. So having an optimal concurrent reads and concurrent writes value will improve Cassandra performance. But raising these values beyond the limit will decrease Cassandra performance. These values are highly tied with CPU cores of the system. As like, Java heap size, there is also a rule of thumb about how to select these values:
  • Concurrent Reads: 4 concurrent reads per processor core
  • Concurrent Writes: Most of the time you do not need it as write is usually fast. If needed, you can set the value to equal or higher than the concurrent reads.
To change the value, you need to update conf/cassandra.yaml configuration file. There are two parameters present for these two: ConcurrentReaders and ConcurrentWriters. Update those values based on your system and restart Cassandra to take the effect.


Tune-Up Key Cache: For each of the column families, key cache holds the location of row keys in memory. Since keys are usually small, it can store a large cache without using much memory. Each cache hit results in less disk activity. 200000 is the default key cache size of Cassandra and its enabled by default. You can alter the default value by following: 

update column family cloud_for_beginners with keys_cached = 300000
view rawupdate_keys_cached hosted with ❤ by GitHub

You can monitor key cache performance by using nodetool cfstats command.

[root@ip-10-0-0-57 ~]# bin/nodetool --host ip-10-0-0-57 cfstats
Column Family: Cloud_For_Beginners
...
Key cache capacity: 200000
Key cache size: 200000
Key cache hit rate: 0.568
view rawnodetool-cfstats hosted with ❤ by GitHub


Tune-Up Row Cache: In Cassandra, row cache is disabled by default. Row cache holds the entire content of the date in memory. So a column family with large rows could easily consume system memory and could impact Cassandra performance, that's why its disabled by default and should be remain disabled in most of the cases. But if your column data is too small then using row cache will significantly improve performance as row cache keeps the most accessed rows hot in memory. To enable row cache, you can alter your column family and can pass number of rows for row cache.

update column family cloud_for_beginners with rows_cached = 1000
view rawupdate_rows_cached hosted with ❤ by GitHub
You can also monitor it by using nodetool cfstats command like above (watch for ."Row cache hit rate").


Conclusion: As I said early, these are only some of the tune-up steps, there are more (high performing RAID level, file system optimization, disabling swap memory, memory mapped disk modes and so on). But I gave you something you can start with, once you find out improved Cassandra performance you can try the rest of the tuning. Cassandra is highly scalable and scaling up is done by enhancing each node (more RAM, high network throughput, SSD, disk size, etc). Remember, if you are using AWS EC2 instance do not expect much performance improvement if you are using medium or small type instance as they are not optimized for better I/O or network, use xlarge+ instance instead.

No comments:

Post a Comment