Apache Cassandra är en NoSQL-databas som utlovar linjär horisontell skalning – dubbelt så många servrar ska alltså fördubbla kapaciteten. I denna artikel gör Citerus konsult Frans Lundberg en testkörning av Cassandra. För testfallet uppnås linjär skalning för läsningar, men inte för skrivningar.
Cassandra utvecklades ursprungligen hos Facebook för att hantera de stora datamängder som deras över en miljard användare genererar. Eftersom Cassandra använder sig av consistent hashing (denna sida har en introduktion) har den potential att skala läsningar och även skrivningar horisontellt och linjärt. I denna artikel beskriver jag en testkörning av Cassandra på ett kluster och delar med mig av resultatet samt mina reflektioner.
Cassandra
Det är lätt att komma igång. På mitt OS (Ubuntu 12.04) fungerade det bra att helt enkelt ladda hem filen: apache-cassandra-2.0.2-bin.tar.gz från cassandra.apache.org och packa upp den i valfritt bibliotek. Sedan körs skriptet “cassandra” för att starta databasen och “cqlsh” för att starta en CQL-terminal.
CQL, Cassandra Query Language, är Cassandra’s språk för att köra databaskommandon. Det är förvillande likt SQL. Man kan lätt tro att man kan göra detsamma med CQL som man kan göra med SQL – men så är inte fallet. Begränsningarna med CQL beror på de naturliga begränsningar som Cassandras datamodel och consistent hashing innebär. Till exempel finns inget stöd för transaktioner, joins och foreign keys. Men för dem med SQL-vana, är CQL ett trevligt och enkelt sätt komma igång.
Med de ordinära inställningarna, lagras datan i Cassandra utan någon naturlig ordning. Två värden med konsekutiva primära nycklar, till exempel 100 och 101, kommer normalt inte att sparas nära varandra. Istället sparas de i en ordning som baseras på hashvärden av 100 respektive 101. Detta gör att man inte kan iterera data i ordning efter nyckeln. Man kan inte heller göra så kallade “range queries” på ett effektivt sätt (man måste söka igenom all data i tabellen).
Sammantaget kan man säga att man bara kan göra effektiva sökningar baserat på en exakt matchning av det indexerade värdet. Det är den stora begränsningen, men samtidigt är det en förutsättning för Cassandras potential att skala horisontellt. Man bör noga tänka igenom vilka sökningar man behöver innan man designar strukturen på sin databas. Cassandra har ett begränsat stöd för ad hoc-frågor jämfört med en traditionell SQL-databas.
Testkörning
Testfallet är enkelt: en miljon rader i en tabell, slumpvis skrivningar och slumpvis läsningar (random access) av rader med korta strängar som primär nyckel.
Tabellen skapas med följande CQL:
create table big (key text primary key, value text);
Sedan skrivs en miljon rader till tabellen med slumpvisa nycklar. Den primära nyckeln “key” är runt 20 tecken långt (ASCII-tecken) och detsamma gäller för “value”. När tabellen är fylld, körs skrivningar som skriver över existerande värden. Skrivningarna skriver över slumpvis valda rader med nya värden och pågår i runt 5 minuter, totala antalet skrivningar noteras. Läsningarna körs separat och består i att läsa värdena för slumpvis valda nycklar.
Läsningarna och skrivningarna körs från ett Javaprogram som använder DataStaxs javabibliotek. Den lägsta konsistensnivån (ConsistencyLevel.ONE) används för både läsningar och skrivningar. Detta ska ge bästa prestanda. Replikeringsfaktorn är två, datan sparas alltså på två ställen. Javaklienten använder Session.executeAsync() i biblioteket, vilket rekommenderas för högsta möjliga prestanda. Objekt av typen PreparedStatement används för att minimera CPU-cykler för parsning.
Resultatet nedan visar hur många läsningar respektive skrivningar som körs per sekund för testfallet och med 2, 4 och 8 noder (servrar) i Cassandra-klustret.