Skip to main content

Overview

The block cache is RocksDB’s primary in-memory cache for uncompressed data blocks read from SST files. It’s critical for read performance, reducing disk I/O by caching frequently accessed blocks.
A properly sized and configured block cache can improve read throughput by orders of magnitude.

Cache Implementations

From cache.h:46-47, RocksDB provides two main cache implementations:

LRU Cache

From cache.h:207-275, the traditional LRU (Least Recently Used) cache:
Creating an LRU cache:
From cache.h:371-476, lock-free cache with better CPU efficiency:
HyperClockCache is now generally recommended over LRUCache for better performance under high concurrency.
Creating HyperClockCache:
Key advantages:
  • Much improved CPU efficiency under parallel load
  • Lock-free implementation reduces contention
  • Larger cache shards (less risk of thrashing)
Caveats:
  • Only for BlockBasedTableOptions::block_cache
  • Not a general-purpose Cache (fixed-size keys expected)
  • Requires anonymous mmap support (Linux, Windows)

Configuration Options

Capacity

From cache.h:129-132:
Sizing guidelines:

Sharding

From cache.h:134-138:
Default (-1) chooses a good value based on capacity. LRUCache benefits more from sharding than HyperClockCache.

Strict Capacity Limit

From cache.h:140-145:
  • true: Insert fails if cache is full and no entries can be evicted
  • false: Insert always succeeds, cache may exceed capacity temporarily

Priority Levels

From advanced_cache.h:61-68 and cache.h:224-246:
Priority pools:
  • HIGH: Index and filter blocks (if cache_index_and_filter_blocks_with_high_priority)
  • LOW: Data blocks (default)
  • BOTTOM: Blob values

Entry Roles

From cache.h:55-88, cache entries are classified by role:

Monitoring by Role

From cache.h:101-110:

Advanced Features

Secondary Cache

From cache.h:159-161, add a compressed secondary tier:
Compressed secondary cache:

Tiered Cache

From cache.h:518-547, experimental multi-tier caching:

Metadata Charging

From cache.h:114-124:
kFullChargeCacheMetadata counts the cache’s internal overhead against capacity for more accurate memory accounting.

Memory Allocator

From cache.h:147-153, use a custom allocator:

Usage Patterns

Insert

From advanced_cache.h:225-266:

Lookup

From advanced_cache.h:281-295:

Async Lookup

From advanced_cache.h:456-543, for non-blocking reads:

Statistics

From statistics.h:32-95, monitor cache performance:
Example monitoring:

Cache Management

Runtime Control

From advanced_cache.h:338-356:

Eviction Callback

From advanced_cache.h:545-554:

Best Practices

Shared vs. Separate Caches: Use a shared cache across all column families to maximize hit rate and avoid fragmentation.

1. Size Appropriately

2. Use HyperClockCache

3. Cache Index and Filters

4. Monitor Hit Rate

5. Use Secondary Cache for Large Datasets

Troubleshooting

Low Hit Rate

  1. Increase cache size: More capacity = better hit rate
  2. Check working set: Cache should hold active working set
  3. Pin critical blocks: Use high priority for index/filters
  4. Monitor entry stats: Identify which block types are missing

High Memory Usage

  1. Enable metadata charging: Use kFullChargeCacheMetadata
  2. Set strict limit: Prevent cache from exceeding capacity
  3. Reduce capacity: Trade hit rate for memory
  4. Use compressed secondary: Offload to compressed tier

Contention (LRU Cache)

  1. Switch to HyperClockCache: Better for high concurrency
  2. Increase sharding: Higher num_shard_bits
  3. Profile mutex wait: Check DB_MUTEX_WAIT_MICROS statistic

See Also