MEMTABLE - The In-Memory Speed Demon
ðū Master Cassandra's write buffer: data structures, flush triggers, memory management, and sub-millisecond performance!
ð Instagram: 1 Billion Writes/Day, Sub-5ms Latency
Instagram's challenge: 1 billion+ users generating massive write traffic. Every like, comment, story, message = write to Cassandra. Peak: 500,000 writes/second! The requirement: Sub-5ms latency (users notice delays > 10ms). Traditional disk-based writes = 10-50ms (too slow!). The solution: Memtable - in-memory write buffer. How it works: Every write goes to memtable FIRST â In-memory sorted tree structure (RAM = instant!). Write latency: 0.1ms â 100 microseconds! 100x faster than disk. Sorted on insert â Maintains partition key + clustering key order. Flush to SSTable later â When memtable reaches 128MB (async). Result: P50 latency: 2.8ms â (0.1ms memtable + 1ms commit log + 1.7ms network). P99 latency: 8ms â (still under 10ms requirement!). 1 billion writes/day â memtable absorbs bursts effortlessly. Users never wait â instant feedback on every action. Instagram Engineering: "The memtable is why Cassandra can handle our write volume. RAM is 100,000x faster than disk - by buffering writes in memory, we achieve sub-millisecond latency at massive scale. The 128MB flush threshold perfectly balances memory usage vs flush frequency. Without memtable, Instagram wouldn't scale!"
ðū What is a Memtable?
Memtable is Cassandra's in-memory write buffer - where speed magic happens!
Definition
What: In-memory sorted data structure
Type: Write buffer (part of LSM tree)
Purpose: Fast writes + recent read cache
Location: JVM heap memory
Per-table: Each table has its own memtable
Volatile: Data lost on crash (commit log protects!)
Why It Exists
Problem: Disk writes are slow (10-50ms)
Solution: Buffer writes in RAM first
Speed: RAM = 0.1ms vs Disk = 10ms
Batch: Flush many writes at once â SSTable
Efficiency: Amortize disk I/O cost
Result: Sub-millisecond write latency!
Lifecycle
1. Create: Empty memtable on startup
2. Fill: Accept writes until threshold (64-128MB)
3. Freeze: Make read-only when full
4. Flush: Write to SSTable on disk
5. Delete: Free memory after flush
6. Repeat: New memtable for next batch
Data Structure
Type: Skip list (concurrent sorted map)
Sorted by: Partition key â Clustering key
Why sorted: Fast lookups + efficient SSTable write
Concurrency: Lock-free for high throughput
Complexity: O(log n) insert and lookup
Typical size: 64-128MB of data
Memory Characteristics
Heap-based: Lives in JVM heap
GC impact: Can cause pauses if too large
Off-heap option: Available to reduce GC
Compression: None (raw data for speed)
Typical usage: 10-20% of heap
Monitoring: Track memtable size carefully
Role in LSM Tree
LSM: Log-Structured Merge Tree
Level 0: Memtable (in memory)
Level 1+: SSTables (on disk)
Write path: Always to memtable first
Read path: Check memtable before SSTables
Merge: Flush creates new SSTable level
ðĄ The Speed Secret
Why is memtable so fast?
RAM vs Disk Physics:
âĒ RAM latency: 100 nanoseconds = 0.0001ms
âĒ SSD latency: 100 microseconds = 0.1ms (1,000x slower)
âĒ HDD latency: 10 milliseconds = 10ms (100,000x slower!)
By keeping recent writes in memtable (RAM), Cassandra avoids disk I/O completely for hot data. This is the foundation of sub-5ms write latency at massive scale. The memtable is Cassandra's secret weapon!
ðģ Data Structure: Skip List Deep Dive
Memtable uses a concurrent skip list for lock-free sorted storage!
Skip List Basics
Type: Probabilistic balanced tree
Layers: Multiple levels of linked lists
Bottom layer: All elements sorted
Higher layers: Express lanes (skip ahead!)
Search: Start top, drop down when needed
Complexity: O(log n) average for all ops
Why Skip List?
Concurrent: Lock-free updates!
No rebalancing: Unlike red-black trees
Simple: Easier to implement than B-trees
Sorted: Maintains order automatically
Fast: O(log n) with low constants
Memory: Efficient space usage
Sort Order
Primary key: Partition key (hash)
Secondary: Clustering key (defines row order)
Example: users (user_id, timestamp)
Sorted by: user_id â timestamp
Why important: Fast range queries
SSTable: Written in same order
Insert Performance
Time complexity: O(log n)
Typical: 10-20 comparisons for 1M rows
Latency: ~100 microseconds
Concurrency: Lock-free (CAS operations)
Throughput: Millions of inserts/sec
Bottleneck: Rarely (memory bandwidth!)
Lookup Performance
Single key: O(log n)
Range scan: O(log n + k) where k = results
Hit rate: 80-95% for recent data
Latency: Sub-millisecond
Cache friendly: Sequential memory access
Miss: Continue to SSTables
Memory Layout
Nodes: Key + Value + Pointers
Overhead: ~20-30 bytes per entry
Fragmentation: Minimal (linked structure)
GC pressure: Can be high if large
Off-heap option: Reduce GC pauses
Typical: 64-128MB total size
âïļ Lock-Free Concurrency
Why lock-free matters:
With locks: Multiple threads compete for lock, one wins, others wait. Throughput limited by lock contention. At high concurrency, performance degrades linearly.
Lock-free (skip list): Use Compare-And-Swap (CAS) atomic operations. Multiple threads can insert simultaneously. No waiting, no contention. Throughput scales with CPU cores!
This is why Cassandra can handle 500,000 writes/sec on a single node - the memtable never blocks!
âïļ Write Operations: Inserts and Updates
Every write goes through the memtable instantly - here's how!
INSERT Operation
Step 1: Find insertion point (binary search)
Step 2: Create new node with data
Step 3: CAS insert into skip list
Step 4: Update memtable size counter
Latency: ~100 microseconds
Thread-safe: Lock-free CAS ensures atomicity
UPDATE Operation
No in-place update! Insert new version instead
Same key: Insert with newer timestamp
Old version: Kept until compaction
Read: Returns newest timestamp
Why: Immutability = lock-free!
Cleanup: Compaction removes old versions
DELETE Operation
Tombstone: Insert deletion marker
Not deleted: Data still in memtable!
Timestamp: Deletion time recorded
Reads: Skip tombstoned entries
Cleanup: Removed during compaction
Why: Fast deletes without searching
Size Tracking
Counter: Track total memtable size
Per-write: Add data size to counter
Overhead: Include node pointers
Threshold: 64-128MB triggers flush
Atomic: Thread-safe increment
Monitoring: Check via JMX metrics
Batch Mutations
BATCH: Multiple writes together
Atomic: All or nothing semantics
Same memtable: All go to same structure
Performance: Amortize overhead
Size check: After batch, check threshold
Benefit: Reduce network roundtrips
Timestamp Management
Mutation timestamp: Microsecond precision
Client-provided: Or server generates
Conflict resolution: Last-Write-Wins (LWW)
Stored: With each column value
Read: Return newest timestamp
Critical: Determines data freshness
⥠Twitter: 400,000 Tweets/Second in Memtable
Twitter's peak write load during major events:
The Challenge:
âĒ Super Bowl, World Cup = 400,000 tweets/second
âĒ Each tweet = INSERT into timelines table
âĒ Must handle bursts without latency spikes
âĒ Users expect instant tweet posting
Memtable Performance:
âĒ Skip list handles 400k inserts/sec per node
âĒ Average insert latency: 95 microseconds
âĒ Lock-free = no contention even at peak
âĒ Memtable absorbs burst (128MB buffer)
âĒ Flush happens async (doesn't block writes!)
Key metric: P99 write latency stayed under 5ms even during Super Bowl peak! The memtable's lock-free skip list scaled linearly with CPU cores. This is why Twitter trusts Cassandra for real-time social feeds!
ð Read Operations: Memtable as Cache
Memtable isn't just for writes - it's also a blazing-fast read cache!
Read Path Priority
Step 1: Check memtable FIRST
Hit: Return data immediately (sub-ms!)
Miss: Continue to SSTables
Why first: Most recent data here
Hit rate: 80-95% for hot data
Benefit: Avoid disk I/O for recent writes
Single Key Lookup
Partition key: Hash to find node
Skip list search: O(log n) traversal
Found: Return value + timestamp
Not found: Check SSTables
Latency: 50-200 microseconds
Efficiency: No disk access needed!
Range Query
Clustering range: Use skip list order
Sequential scan: After finding start
Performance: O(log n + k) where k = rows
Efficient: Sorted structure = fast scan
Merge: Combine with SSTable results
Typical: Faster than SSTables!
Cache Hit Benefits
No disk I/O: Skip SSTable read
No bloom filter: Skip probabilistic check
No index lookup: Direct memory access
Latency: <1ms vs 10-50ms disk
Throughput: Millions of reads/sec
Cost: No I/O cost!
Read-Write Consistency
Write then read: Always see latest
Same node: Memtable guarantees freshness
Timestamp: Newest version returned
No stale reads: Within same node
Distributed: CL determines freshness
Local consistency: Perfect!
Multi-Memtable Reads
Active memtable: Check current first
Flushing memtables: Check frozen too
Multiple: During flush, 2+ exist
Merge: Combine results by timestamp
Rare: Usually only 1 memtable
Performance: Still sub-millisecond
ð Read Performance Impact
Memtable cache hit rates matter A LOT:
95% hit rate: P99 latency = 2ms (mostly memtable)
50% hit rate: P99 latency = 15ms (half go to disk)
10% hit rate: P99 latency = 50ms (mostly disk I/O)
For read-heavy workloads, keeping your working set in memtable is CRITICAL for performance. This is why larger memtables (128MB vs 64MB) can dramatically improve read latency!
⥠Flush Triggers: When Memtable Becomes SSTable
Understanding flush triggers is critical for tuning Cassandra performance!
1. Size Threshold (Primary)
Default: 64MB per table memtable
Configurable: 32-256MB typical range
When: Memtable reaches threshold size
Trigger: Automatic background flush
Frequency: Depends on write rate
Config: memtable_heap_space_in_mb
2. Time-Based Flush
Default: 1 hour (3600 seconds)
Purpose: Prevent stale data in memory
When: Even if size not reached
Why: Free commit log space
Low traffic: Tables flush eventually
Config: memtable_flush_period_in_ms
3. Memory Pressure
Trigger: Total memtable memory > threshold
Threshold: Typically 2-4GB total
Action: Flush largest memtable first
Emergency: Prevent OOM (out of memory)
Cascading: Flush multiple if needed
Monitoring: Watch total memtable size
4. Commit Log Pressure
Trigger: Commit log size exceeds limit
Default: Usually 8GB total
Problem: Can't truncate commit log
Solution: Force memtable flush
Why: Allow commit log cleanup
Impact: May flush smaller memtables
5. Manual Flush
Command: nodetool flush [keyspace] [table]
When: Operator initiated
Use cases: Before backup, repair, upgrade
Effect: All memtables flushed immediately
Blocks: Waits for flush completion
Safe: No data loss risk
6. Shutdown Flush
When: Node gracefully stopped
Action: Flush ALL memtables
Purpose: Minimize commit log replay
Duration: Can take 1-5 minutes
Skip: Kill -9 doesn't flush (unsafe!)
Result: Clean shutdown, fast restart
âïļ Tuning Flush Threshold
Larger memtable (128-256MB):
â
Fewer flushes = less I/O overhead
â
Better compression (more data = better ratios)
â
Higher cache hit rate (more data in RAM)
â Longer flush time (more data to write)
â More memory usage
â Longer commit log replay on crash
Smaller memtable (32-64MB):
â
Faster flush (less data to write)
â
Less memory usage
â
Faster crash recovery
â More frequent flushes = more I/O
â More SSTables = slower reads
Sweet spot: 64-128MB for most workloads!
ð§ Memory Management: Heap vs Off-Heap
Proper memory management is critical for stability and performance!
Heap-based Memtable
Default: Lives in JVM heap
Allocation: Standard Java objects
GC impact: Part of GC scanning
Pros: Simple, fast allocation
Cons: GC pauses with large heaps
Typical: 10-20% of heap size
Off-heap Memtable
Available: Cassandra 2.1+
Location: Direct ByteBuffer (native memory)
GC impact: Minimal (not scanned!)
Pros: No GC pauses from memtable
Cons: Slower allocation, more complex
Config: memtable_allocation_type: offheap_objects
GC Pause Impact
Small heap (8GB): GC pauses <100ms â
Medium heap (16GB): Pauses 200-500ms â ïļ
Large heap (32GB+): Pauses 1-5s â
Memtable contribution: 20-40% of pause time
Solution: Use off-heap or G1GC
Monitoring: Track GC pause frequency
Total Memory Budget
Heap allocation: 8-16GB typical
Memtable: 1-3GB (10-20% of heap)
Row cache: 0-2GB (optional)
Other: 5-11GB (bloom filters, index, buffers)
Off-heap: OS file cache uses remaining RAM
Recommendation: Leave 50% RAM for OS cache
Memory Configuration
memtable_heap_space_in_mb: Max total size
Default: 1/4 of heap
memtable_offheap_space_in_mb: Off-heap limit
memtable_cleanup_threshold: Flush trigger
JVM heap: -Xms8G -Xmx8G (example)
Monitoring: nodetool info | grep Memtable
Heap vs Off-heap Trade-offs
Use heap when: Heap <16GB, simple setup
Use off-heap when: GC pauses >200ms
Heap benefit: Faster allocation, simpler
Off-heap benefit: No GC pauses
Performance: Similar (not a magic bullet!)
Most common: Heap-based with G1GC
ð§ Netflix: Solving GC Pauses with Off-heap
Netflix's GC problem:
Before (heap memtable):
âĒ 32GB heap with 4GB memtable space
âĒ GC pauses: 2-5 seconds (terrible!)
âĒ P99 latency spikes to 6 seconds during GC
âĒ Users see buffering/errors during pauses
âĒ Problem: Large heap + large memtables = long GC
After (off-heap memtable):
âĒ Reduced heap to 16GB
âĒ 4GB memtable moved off-heap
âĒ GC pauses: 100-200ms (95% reduction!)
âĒ P99 latency: 15ms (consistent)
âĒ Zero user-visible pauses â
Configuration:
âĒ memtable_allocation_type: offheap_objects
âĒ memtable_offheap_space_in_mb: 4096
âĒ JVM: -Xms16G -Xmx16G + G1GC
Netflix Engineering: "Moving memtables off-heap was transformative. GC pauses dropped from 5 seconds to 200ms. The trade-off is minimal - allocation is slightly slower, but that's nothing compared to eliminating multi-second pauses. For large heaps (>16GB), off-heap memtables are essential!"
ð Performance Characteristics
Understanding memtable performance limits helps with capacity planning!
Write Throughput
Single node: 100,000-500,000 writes/sec
Limited by: CPU cores (lock-free scales!)
8 cores: ~200,000 writes/sec
16 cores: ~400,000 writes/sec
Not limited by: Memory (until GC pressure)
Bottleneck: Usually network or commit log
Read Throughput
Cache hit: 1,000,000+ reads/sec
Latency: 50-200 microseconds
Limited by: Memory bandwidth
Sequential scan: Very fast (sorted!)
Random access: O(log n) still fast
Miss: Continue to SSTables (slower)
Latency Breakdown
Write operation:
âĒ Serialize: 20Ξs
âĒ Memtable insert: 100Ξs
âĒ Commit log: 1000Ξs (1ms)
âĒ Total: ~1.2ms
Read operation:
âĒ Memtable lookup: 100Ξs
âĒ If miss, SSTable: +10ms
Memory Efficiency
Data overhead: 20-30 bytes per entry
Compression: None (speed over space)
Typical ratio: 1.2-1.5x raw data size
128MB memtable: ~100MB actual data
Efficient: Skip list = low overhead
Compare SSTable: 3-5x compression possible
Scaling Characteristics
CPU cores: Linear scaling (lock-free!)
Memory: More = higher hit rate
Flush frequency: Larger = fewer flushes
Tables: Each has own memtable
50 tables: 50x memory requirement
Limitation: Total memory budget
Real Benchmarks
Test: 16-core server, 32GB RAM
Write: 380,000 ops/sec sustained
Read (hit): 1.2M ops/sec
P50 latency: 0.8ms write, 0.15ms read
P99 latency: 2.5ms write, 0.5ms read
CPU: 70% utilized, GC <5%
ðĒ Real Company Memtable Strategies
ðą WhatsApp: 1 Billion Users, 256MB Memtables
Scale: 1B+ users, 100B+ messages/day
Challenge: Minimize latency for message delivery
Configuration:
âĒ memtable_heap_space_in_mb: 256 (2x default!)
âĒ Why larger: Fewer flushes = more stable latency
âĒ Trade-off: More memory, but worth it
âĒ JVM heap: 24GB (16GB for memtables)
âĒ GC: G1GC with off-heap option
Results:
âĒ Flush frequency: Every 10 minutes (vs 2-3 min default)
âĒ P99 latency: 4ms (consistent!)
âĒ No latency spikes during flush
âĒ Cache hit rate: 97% (larger memtable = more hits!)
âĒ GC pauses: <100ms average
Key insight: Larger memtables reduce flush frequency and improve cache hit rates. The extra memory cost is worth it for latency-sensitive workloads!
ðĩ Spotify: Off-heap for User Listening Data
Use case: Track user listening history (billions of plays)
Problem: Large heap causing 3-5s GC pauses
Solution:
âĒ Switched to off-heap memtables
âĒ memtable_allocation_type: offheap_objects
âĒ memtable_offheap_space_in_mb: 8192 (8GB!)
âĒ Reduced JVM heap: 32GB â 16GB
âĒ More RAM for OS file cache
Before (heap):
âĒ GC pauses: 3-5 seconds
âĒ P99 latency: 6 seconds (during GC)
âĒ User-facing errors during pauses
After (off-heap):
âĒ GC pauses: 150ms average â
âĒ P99 latency: 12ms â
âĒ Zero user-facing errors â
âĒ 96% reduction in GC pause time!
Spotify Engineering: "Off-heap memtables transformed our stability. The 5-second GC pauses were killing us. Now with off-heap, we get all the benefits of large memtables without the GC penalty!"
ðŪ Blizzard: 32MB Memtables for Predictable Performance
Use case: World of Warcraft game state (millions of players)
Requirement: Predictable low latency (game feel!)
Strategy:
âĒ Smaller memtables: 32MB (vs 64-128MB typical)
âĒ Why: More frequent flushes = more predictable
âĒ Flush every 30-60 seconds (fast!)
âĒ SSTable count higher, but acceptable
âĒ Trade-off: More I/O for consistency
Benefits:
âĒ Latency variance: Very low (5ms Âą 1ms)
âĒ No large flush delays
âĒ Predictable commit log size
âĒ Fast crash recovery (<30 seconds)
âĒ Memory pressure: Lower
Key insight: Smaller memtables = more predictable behavior. For latency-sensitive gaming workloads, consistency matters more than peak throughput!
â Best Practices: Memtable Optimization
1. Size Memtables Appropriately
Default 64MB: Good starting point
High write load: 128-256MB
Low latency need: 32-64MB
Rule of thumb: Flush every 2-10 minutes
Monitor: nodetool tablestats
Adjust: Based on flush frequency
2. Monitor Memory Usage
Total memtable size: Should be <25% heap
Alert threshold: >30% heap = problem
Check: nodetool info | grep Memtable
GC impact: Watch pause times
Action: If >30%, reduce memtable size
Tools: JMX metrics, Prometheus
3. Use Off-heap for Large Heaps
If heap >16GB: Consider off-heap
If GC >200ms: Definitely use off-heap!
Config: memtable_allocation_type: offheap_objects
Benefit: Eliminate memtable GC pauses
Cost: Slightly slower allocation
Worth it: For large deployments
4. Limit Number of Tables
Each table: Has its own memtable
100 tables: = 100x memory requirement
Problem: Memory fragmentation
Recommendation: <50 tables per node
Alternative: Use larger nodes
Anti-pattern: One table per user (bad!)
5. Tune Flush Writers
memtable_flush_writers: Parallel flush threads
Default: 2 threads
High write load: Increase to 4-8
Benefit: Faster flush = less memory pressure
Trade-off: More disk I/O concurrency
Monitor: Flush queue depth
6. Test Memtable Size Changes
Don't assume: Bigger is always better
Benchmark: Test different sizes
Measure: Latency, flush freq, GC pauses
Sweet spot: Different per workload
Load test: Simulate production traffic
Monitor: P99 latency under load
ðĻ Common Mistakes
- â Memtables too large: GC pauses kill performance (use off-heap!)
- â Too many tables: Each has memtable = memory explosion
- â Ignoring GC pauses: >500ms = major problem
- â Not monitoring flush frequency: Too frequent = I/O storm
- â Heap-based with >16GB heap: Use off-heap instead!
- â Assuming defaults are optimal: Tune for your workload!
ðž Interview Questions & Answers
Complete Answer:
A memtable is Cassandra's in-memory write buffer - a sorted data structure that temporarily holds recent writes before they're flushed to disk as SSTables.
What is Memtable:
- Structure: Concurrent skip list (lock-free sorted tree)
- Location: JVM heap memory (or off-heap)
- Per-table: Each Cassandra table has its own memtable
- Size: Typically 64-128MB before flush
- Sorted: Maintains order by partition key â clustering key
- Volatile: Data lost on crash (protected by commit log)
Why Critical for Write Performance:
1. RAM is 100,000x faster than disk:
- RAM access: 100 nanoseconds = 0.0001ms
- SSD access: 100 microseconds = 0.1ms (1,000x slower)
- HDD access: 10 milliseconds (100,000x slower!)
- Writing to memtable = writing to RAM = instant!
2. Batches writes to amortize disk I/O:
- Instead of writing each mutation to disk individually
- Accumulate many writes in memtable (64-128MB)
- Flush all at once to SSTable
- One big sequential write >> many small random writes
- Reduces disk I/O overhead by 100-1000x!
3. Provides sorted structure:
- Skip list maintains sort order automatically
- When flushed, SSTable is already sorted
- No need to sort on flush (would be slow!)
- Makes range queries fast
Write Path Flow:
- Write arrives at coordinator
- Write to commit log (durability) - 1ms
- Write to memtable (performance) - 0.1ms
- Return SUCCESS to client - total ~3ms
- Later: Flush memtable to SSTable (async)
Performance Impact:
Without memtable: Every write = disk I/O = 10-50ms latency
With memtable: Every write = RAM access = 0.1ms latency
Result: 100-500x faster writes!
Flush Process:
- When memtable reaches 64-128MB threshold
- Freeze current memtable (make read-only)
- Create new empty memtable (1ms operation)
- Flush frozen memtable to SSTable in background (2-5 seconds)
- Writes never blocked - go to new memtable immediately!
Key Insight: The memtable is the foundation of Cassandra's write performance. By buffering writes in RAM and batching disk I/O, Cassandra achieves sub-5ms write latency even at 500,000 writes/second. This is what makes Cassandra suitable for write-heavy workloads like time-series data, logging, and real-time analytics!
Complete Answer:
Cassandra uses a concurrent skip list for memtable because it provides O(log n) operations with lock-free concurrency - critical for high-throughput writes.
Skip List Basics:
- Structure: Multiple levels of sorted linked lists
- Bottom level: All elements in sorted order
- Higher levels: "Express lanes" that skip ahead
- Search: Start at top level, drop down when needed
- Probabilistic: Random promotion to higher levels
- Complexity: O(log n) average for insert, search, delete
Why Skip List vs Alternatives:
Skip List vs Red-Black Tree:
- Skip list advantage: Lock-free concurrent updates!
- Red-black tree requires locking for rebalancing
- Lock contention kills throughput at high concurrency
- Skip list: Use Compare-And-Swap (CAS) operations
- Multiple threads can insert simultaneously without waiting
- Throughput scales linearly with CPU cores
- Skip list advantage: Simpler implementation
- No complex rotation/rebalancing logic
- Easier to reason about correctness
Skip List vs Hash Table:
- Skip list: Maintains sorted order
- Hash table: No inherent order
- Critical: Cassandra needs sort order for clustering keys
- Range queries require sorted structure
- SSTable flush requires sorted data
- Skip list: Range scan is O(log n + k)
- Hash table: Range scan would be O(n)
Skip List vs B-tree:
- Skip list advantage: Better for in-memory
- B-tree optimized for disk (minimize seeks)
- In memory, simpler structure wins
- Skip list advantage: Lock-free possible
- B-tree difficult to make lock-free (complex balancing)
- Skip list: Lower constant factors
- Fewer pointer chases than B-tree
Lock-Free Concurrency Deep Dive:
This is THE critical reason Cassandra uses skip list!
Problem with locks:
- Thread A acquires lock, inserts data
- Threads B, C, D wait for lock
- At high concurrency (100+ threads), massive contention
- Throughput degrades as threads increase
Skip list lock-free approach:
- Use atomic CAS (Compare-And-Swap) operations
- Insert attempts: CAS(node.next, NULL, new_node)
- If CAS fails (another thread inserted), retry
- No waiting, no blocking
- All threads make progress simultaneously
- Throughput scales linearly with cores!
Real Performance Impact:
Benchmark: 16-core server, concurrent inserts:
Red-black tree (locked): 50,000 inserts/sec (lock contention)
Skip list (lock-free): 400,000 inserts/sec (8x faster!)
Scaling: Skip list throughput increases with cores, locked structure plateaus
Trade-offs:
- Skip list downside: Probabilistic (not guaranteed O(log n))
- In practice: Very rare to degrade
- Skip list downside: Pointer overhead
- Each node needs multiple next pointers (for levels)
- ~20-30 bytes overhead per entry
- Acceptable for in-memory structure
Key Insight: The skip list's lock-free property is what enables Cassandra to handle 500,000 writes/second on a single node. Any locked data structure would become a bottleneck at that scale. The combination of O(log n) operations, sorted order, and lock-free concurrency makes skip list the perfect choice for memtable!
Responsive Ad