☀️Siang
Database

Apache Cassandra: NoSQL Distributed Database

Data model, CQL, replication, consistency, compaction — panduan lengkap memahami dan menggunakan Cassandra untuk aplikasi skala besar

Artikel: Cassandra Basics Artikel: Cassandra Basics


1. Pengenalan Apache Cassandra

Apache Cassandra adalah NoSQL database yang dirancang untuk menangani data dalam skala sangat besar dengan ketersediaan tinggi (high availability). Dikembangkan oleh Facebook pada tahun 2008 dan kemudian dijadikan open source oleh Apache Foundation.

Cassandra banyak digunakan oleh perusahaan besar seperti Instagram, Netflix, Apple, Uber, dan Discord untuk menyimpan miliaran baris data dengan throughput tinggi.

Kapan Menggunakan Cassandra?

Fitur Cassandra MySQL/PostgreSQL
TipeNoSQL (Wide-column store)Relational (SQL)
SkalaHorizontal (tambah node)Vertikal (tambah resource)
KetersediaanTidak ada single point of failurePerlu setup master-slave
QueryCQL (subset SQL)Full SQL
JOINTidak mendukungMendukung
ACID TransactionHanya single partitionFull ACID
KonsistensiTunable (eventual → strong)Strong (default)
Cocok untukTime-series, IoT, logging, social mediaE-commerce, ERP, CRUD apps
💡 Rule of Thumb

Gunakan Cassandra jika: (1) data Anda terukur dalam miliaran baris, (2) butuh high availability 24/7, (3) query polanya sederhana (berdasarkan key), (4) write-heavy workload. Jika butuh JOIN kompleks atau transaction multi-tabel, tetap pakai RDBMS.

Instalasi Cassandra

Diagram: Arsitektur Cassandra Cluster

Node 1 Token: 0 Data: A-F

Node 2 Token: 28 Data: G-M

Node 3 Token: 56 Data: N-S

Node 4 Token: 84 Data: T-Z

Node 5 Token: 112 Replica

Node 6 Token: 140 Replica

Client

Key Concepts: ● Client → ANY node bisa menerima...

Komponen Utama

Komponen Fungsi
NodeSatu server dalam cluster
Data CenterKumpulan node di lokasi yang sama
ClusterKumpulan semua node
Commit LogWrite-ahead log untuk durability
MemTableIn-memory buffer untuk write
SSTableSorted String Table — immutable data on disk
Gossip ProtocolNode-to-node communication untuk info cluster
SnitchMenentukan topology jaringan dan proximity

Write Path

Diagram: Write Path di Cassandra

Client

Commit Log

MemTable (in-memory)

SSTable (on disk)

Replicate to N nodes

/"● Write = append-only (fast sequential I...



3. Data Model — Keyspace, Tabel, Kolom

Data model Cassandra berbeda dari RDBMS. Yang paling penting: data modeling di Cassandra dimulai dari query, bukan dari entitas (unlike RDBMS yang dimulai dari normalisasi).

Diagram

PRIMARY KEY (customer_id, order_date, order_id)...

Partition Key customer_id

Clustering Column order_date

Clustering Column order_id

● Partition Key → tentukan node penyimpanan ● C...

CQL — Primary Key Patterns
-- =============================================
-- PATTERN 1: Single Column Primary Key
-- =============================================
-- product_id = partition key (dan satu-satunya key)
CREATE TABLE products (
    product_id UUID PRIMARY KEY,
    name TEXT,
    price DECIMAL
);
-- Query: SELECT * FROM products WHERE product_id = ?


-- =============================================
-- PATTERN 2: Composite Partition Key + Clustering
-- =============================================
-- customer_id = partition key
-- order_date  = clustering column (diurutkan ASC)
CREATE TABLE orders_by_date (
    customer_id UUID,
    order_date  DATE,
    order_id    TIMEUUID,
    total       DECIMAL,
    status      TEXT,
    PRIMARY KEY (customer_id, order_date, order_id)
);
-- Query: SELECT * FROM orders_by_date WHERE customer_id = ? AND order_date = ?


-- =============================================
-- PATTERN 3: Composite Partition Key
-- =============================================
-- (sensor_id, date) = composite partition key
-- time = clustering column
CREATE TABLE sensor_readings (
    sensor_id  UUID,
    date       DATE,
    time       TIMEUUID,
    value      DOUBLE,
    unit       TEXT,
    PRIMARY KEY ((sensor_id, date), time)
) WITH CLUSTERING ORDER BY (time DESC);
-- Query: SELECT * FROM sensor_readings
--        WHERE sensor_id = ? AND date = ? AND time > ?


-- =============================================
-- PATTERN 4: Tabel denormalized per query
-- =============================================
-- Data yang SAMA disimpan di tabel berbeda untuk query berbeda!
-- Ini NORMAL di Cassandra (bukan redundansi)

-- Query 1: "Tampilkan semua order customer X"
CREATE TABLE orders_by_customer (
    customer_id UUID,
    order_id    TIMEUUID,
    product     TEXT,
    total       DECIMAL,
    PRIMARY KEY (customer_id, order_id)
) WITH CLUSTERING ORDER BY (order_id DESC);

-- Query 2: "Tampilkan semua order untuk produk Y"
CREATE TABLE orders_by_product (
    product_id  UUID,
    order_id    TIMEUUID,
    customer_id UUID,
    total       DECIMAL,
    PRIMARY KEY (product_id, order_id)
) WITH CLUSTERING ORDER BY (order_id DESC);
-- Data yang sama, dua tabel berbeda, untuk dua query berbeda!
💡 Golden Rule: Satu Query = Satu Tabel

Di Cassandra, Anda merancang tabel berdasarkan query yang dibutuhkan, bukan berdasarkan entitas data. Jika punya 5 query berbeda, bisa jadi butuh 5 tabel berbeda (denormalized). Ini berbeda 180° dari RDBMS!



6. Replication Strategy

Replication factor menentukan berapa salinan (copy) data yang disimpan di cluster. Replication factor 3 = setiap data disimpan di 3 node berbeda.

CQL — Replication Strategy
-- =============================================
-- SIMPLE STRATEGY
-- =============================================
-- Cocok untuk single datacenter / development
-- Menyimpan replica pada node berikutnya secara clockwise
CREATE KEYSPACE dev_keyspace
WITH replication = {
    'class': 'SimpleStrategy',
    'replication_factor': 3
};

-- =============================================
-- NETWORK TOPOLOGY STRATEGY (Produksi!)
-- =============================================
-- Cocok untuk multi-datacenter
-- Memperhatikan rack awareness
CREATE KEYSPACE production
WITH replication = {
    'class': 'NetworkTopologyStrategy',
    'dc_jakarta': 3,     -- 3 replica di Jakarta DC
    'dc_singapore': 2    -- 2 replica di Singapore DC
};

-- =============================================
-- Mengubah replication factor
-- =============================================
ALTER KEYSPACE production
WITH replication = {
    'class': 'NetworkTopologyStrategy',
    'dc_jakarta': 3,
    'dc_singapore': 3    -- tambah dari 2 ke 3
};

-- Cek replication setting
DESCRIBE KEYSPACE production;

-- =============================================
-- Repair (setelah ubah replication)
-- =============================================
-- Harus dijalankan setelah ubah replication factor
nodetool repair production


7. Consistency Level

Cassandra mendukung tunable consistency — Anda bisa memilih tingkat konsistensi per query. Semakin tinggi konsistensi, semakin lambat tapi semakin akurat.

Tingkat Konsistensi

Level Penjelasan Cocok Untuk
ONE1 node mengkonfirmasiWrite cepat, toleransi hilang sementara
TWO2 node mengkonfirmasiBalance antara speed dan consistency
THREE3 node mengkonfirmasiLebih konsisten, perlu RF >= 3
QUORUMMayoritas node (N/2 + 1)Produksi — recommended
ALLSemua replica mengkonfirmasiStrong consistency, tapi lambat
LOCAL_QUORUMMayoritas di datacenter lokalMulti-DC — recommended
EACH_QUORUMMayoritas di setiap datacenterMulti-DC strong consistency
CQL — Consistency Level
-- =============================================
-- SET CONSISTENCY PER SESSION
-- =============================================
CONSISTENCY QUORUM;
CONSISTENCY LOCAL_QUORUM;
CONSISTENCY ONE;

-- Cek consistency saat ini
CONSISTENCY;


-- =============================================
-- FORMULA: Read + Write Consistency
-- =============================================
-- Strong Consistency: R + W > Replication Factor
--
-- Contoh: RF = 3
--   Write QUORUM (2) + Read QUORUM (2) = 4 > 3 → Strong!
--   Write ONE (1)    + Read ALL (3)    = 4 > 3 → Strong!
--   Write ONE (1)    + Read ONE (1)    = 2 < 3 → Eventual!
--
-- Recommendation produksi (RF=3):
--   Write = LOCAL_QUORUM
--   Read  = LOCAL_QUORUM
--   → Strong consistency, toleransi 1 node down


-- =============================================
-- CONTOH: Write dengan consistency
-- =============================================
INSERT INTO orders (customer_id, order_id, total)
VALUES (a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11, now(), 500000)
USING CONSISTENCY LOCAL_QUORUM;

-- CONTOH: Read dengan consistency
SELECT * FROM orders
WHERE customer_id = a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11
USING CONSISTENCY LOCAL_QUORUM;


8. Data Modeling — Query-First Approach

Data modeling di Cassandra dimulai dari query, bukan dari entitas. Langkahnya: (1) Identifikasi semua query, (2) Buat tabel per query, (3) Pilih partition key yang baik.

CQL — Data Modeling Skenario E-Commerce
-- =============================================
-- SKENARIO: Toko Online
-- Query yang dibutuhkan:
-- Q1: Tampilkan semua produk di kategori tertentu
-- Q2: Tampilkan semua pesanan customer
-- Q3: Tampilkan pesanan terbaru di semua customer
-- Q4: Cari produk berdasarkan nama
-- =============================================

-- Q1: Produk per kategori
CREATE TABLE products_by_category (
    category    TEXT,
    product_id  UUID,
    name        TEXT,
    price       DECIMAL,
    stock       INT,
    PRIMARY KEY (category, product_id)
);

-- Q2: Pesanan per customer (terbaru duluan)
CREATE TABLE orders_by_customer (
    customer_id UUID,
    order_date  TIMESTAMP,
    order_id    UUID,
    product     TEXT,
    quantity    INT,
    total       DECIMAL,
    status      TEXT,
    PRIMARY KEY (customer_id, order_date, order_id)
) WITH CLUSTERING ORDER BY (order_date DESC, order_id ASC);

-- Q3: Pesanan terbaru global (gunakan bucket per hari)
CREATE TABLE orders_by_day (
    day_bucket  DATE,        -- partition key: 2026-06-26
    order_time  TIMESTAMP,   -- clustering
    order_id    UUID,
    customer_id UUID,
    total       DECIMAL,
    PRIMARY KEY (day_bucket, order_time, order_id)
) WITH CLUSTERING ORDER BY (order_time DESC, order_id ASC);

-- Q4: Search produk berdasarkan nama (secondary index)
CREATE TABLE products_by_name (
    first_letter TEXT,       -- partition: 'A', 'B', ...
    product_name TEXT,
    product_id   UUID,
    price        DECIMAL,
    PRIMARY KEY (first_letter, product_name, product_id)
);

Best Practice: Avoid Large Partitions

Aturan Detail
Max partition size~100MB (ideal < 10MB)
Max rows per partition~100.000 baris
Bucket strategyGunakan time bucket (hari/bulan) untuk data time-series
Partition keyPilih key yang mendistribusikan data merata


9. TTL & Lightweight Transactions

CQL — TTL & Lightweight Transactions
-- =============================================
-- TTL (Time To Live)
-- =============================================
-- Data otomatis dihapus setelah waktu tertentu

-- Insert dengan TTL 1 jam (3600 detik)
INSERT INTO sensor_readings (sensor_id, date, time, value, unit)
VALUES (uuid(), '2026-06-26', now(), 25.5, 'celsius')
USING TTL 3600;

-- Insert dengan TTL 30 hari
INSERT INTO session_data (session_id, user_id, data)
VALUES (uuid(), uuid(), 'session_info')
USING TTL 2592000;  -- 30 * 24 * 60 * 60

-- Cek TTL yang tersisa
SELECT TTL(unit) FROM sensor_readings
WHERE sensor_id = xxx AND date = '2026-06-26';

-- Update TTL (perpanjang)
UPDATE sensor_readings USING TTL 7200
SET unit = 'celsius'
WHERE sensor_id = xxx AND date = '2026-06-26';

-- Hapus TTL (jadikan permanent)
UPDATE sensor_readings USING TTL 0
SET unit = 'celsius'
WHERE sensor_id = xxx AND date = '2026-06-26';


-- =============================================
-- LIGHTWEIGHT TRANSACTIONS (LWT)
-- =============================================
-- Compare-and-set: insert/update hanya jika kondisi terpenuhi
-- Berguna untuk uniqueness check

-- Insert hanya jika belum ada
INSERT INTO users (username, email, name)
VALUES ('johndoe', 'john@email.com', 'John Doe')
IF NOT EXISTS;

-- Update hanya jika nilai saat ini sesuai
UPDATE accounts SET balance = balance - 100000
WHERE account_id = xxx
IF balance >= 100000;

-- Result: applied = TRUE jika berhasil, FALSE jika gagal
-- [applied] | balance
-- ----------+--------
-- True      | 500000


-- =============================================
-- USER-DEFINED TYPES (UDT)
-- =============================================
CREATE TYPE address_type (
    street TEXT,
    city TEXT,
    province TEXT,
    postal_code TEXT
);

CREATE TABLE customers (
    customer_id UUID PRIMARY KEY,
    name TEXT,
    address FROZEN,
    billing_address FROZEN
);

INSERT INTO customers (customer_id, name, address)
VALUES (uuid(), 'Budi', {street: 'Jl. Sudirman 123', city: 'Jakarta',
                          province: 'DKI Jakarta', postal_code: '12190'});


10. Compaction & Maintenance

CQL & Bash — Compaction & Maintenance
-- =============================================
-- COMPACTION STRATEGY
-- =============================================
-- Compaction = proses merge SSTable yang sudah expired/tidak relevan

-- STCS (SizeTieredCompactionStrategy) — default
-- Cocok untuk write-heavy, jarang update
CREATE TABLE logs (
    id UUID PRIMARY KEY,
    message TEXT,
    created_at TIMESTAMP
) WITH compaction = {
    'class': 'SizeTieredCompactionStrategy',
    'min_threshold': 4,
    'max_threshold': 32
};

-- LCS (LeveledCompactionStrategy)
-- Cocok untuk read-heavy, sering update
CREATE TABLE user_profiles (
    user_id UUID PRIMARY KEY,
    name TEXT,
    email TEXT
) WITH compaction = {
    'class': 'LeveledCompactionStrategy'
};

-- TWCS (TimeWindowCompactionStrategy)
-- Cocok untuk time-series data dengan TTL
CREATE TABLE metrics (
    metric_id UUID,
    timestamp TIMESTAMP,
    value DOUBLE,
    PRIMARY KEY (metric_id, timestamp)
) WITH compaction = {
    'class': 'TimeWindowCompactionStrategy',
    'compaction_window_size': 1,
    'compaction_window_unit': 'DAYS'
};

Bash — Maintenance Commands
# =============================================
# NODETOOL — Maintenance Commands
# =============================================

# Cek status cluster
nodetool status

# Cek info node
nodetool info

# Cek ring (token distribution)
nodetool ring

# Flush memtable ke SSTable
nodetool flush

# Cleanup (hapus data yang bukan milik node ini)
nodetool cleanup

# Repair (sinkronisasi data antar replica)
nodetool repair ecommerce

# Compaction stats
nodetool compactionstats

# Cek tablestats
nodetool tablestats ecommerce.orders_by_customer

# Garbage collect tombstones
nodetool garbagecollect ecommerce orders_by_customer

# =============================================
# MONITORING
# =============================================
# Cek ukuran data per tabel
nodetool tablestats ecommerce

# Cek latensi
nodetool tablehistograms ecommerce orders_by_customer

# Snapshot (backup)
nodetool snapshot ecommerce -t my_backup_2026


11. Quiz: Uji Pemahamanmu!

Setelah membaca tutorial di atas, jawablah 5 pertanyaan berikut untuk menguji pemahamanmu tentang Cassandra:

Pertanyaan 1: Apa perbedaan Partition Key dan Clustering Column di Cassandra?

a) Partition Key mengurutkan data, Clustering Column mendistribusikan data
b) Partition Key mendistribusikan data ke node, Clustering Column mengurutkan data dalam partition
c) Keduanya sama saja
d) Partition Key hanya untuk single column

Pertanyaan 2: Mengapa Cassandra tidak mendukung JOIN?

a) Karena Cassandra masih dalam pengembangan
b) Karena data tersebar di banyak node, JOIN antar-partition sangat tidak efisien
c) Karena Cassandra hanya mendukung SELECT *
d) JOIN bisa dilakukan dengan secondary index

Pertanyaan 3: Consistency level apa yang direkomendasikan untuk produksi multi-datacenter?

a) ONE
b) ALL
c) LOCAL_QUORUM
d) ANY

Pertanyaan 4: Apa itu TTL di Cassandra?

a) Total Volume Limit — batas ukuran tabel
b) Time To Live — data otomatis dihapus setelah waktu tertentu
c) Token Value Locator — untuk distribusi data
d) Table Validation Lock — untuk konsistensi

Pertanyaan 5: Pendekatan data modeling di Cassandra dimulai dari?

a) Normalisasi tabel seperti RDBMS
b) Identifikasi entitas data terlebih dahulu
c) Identifikasi query yang dibutuhkan (query-first)
d) Membuat ERD (Entity Relationship Diagram)
🔍 Zoom
100%
🎨 Tema