sstableloader
Bulk loads SSTables from a directory into a live Cassandra cluster.
Synopsis
Section titled “Synopsis”sstableloader [options] <dir_path>Description
Section titled “Description”sstableloader streams SSTable files from a local directory into a running Cassandra cluster. It reads SSTables from disk and uses Cassandra's streaming protocol to distribute the data to the appropriate nodes based on the cluster's token ranges.
This tool is essential for:
- Restoring data from snapshots to a different cluster
- Migrating data between clusters
- Bulk loading externally generated SSTables
- Disaster recovery when rebuilding a cluster
Unique Among SSTable Tools
Unlike most SSTable tools, sstableloader connects to a running Cassandra cluster. The source node (where the tool runs) does not need Cassandra running, but the target cluster must be operational.
How It Works
Section titled “How It Works”Directory Structure Requirements
Section titled “Directory Structure Requirements”The directory path must follow Cassandra's data directory structure:
<base_path>/<keyspace>/<table>/
Examples:/tmp/restore/my_keyspace/users/ # Correct - plain table name/tmp/restore/my_keyspace/users-a1b2c3d4e5f6g7h8/ # Correct - table with UUID suffix/var/backup/cycling/cyclist_name/ # Correct/restore/my_keyspace/my_table/snapshots/ # Incorrect - extra directory levelOn-Disk Table Directory Names
Cassandra stores tables with UUID suffixes (e.g., users-a1b2c3d4e5f6g7h8). When loading from live data or snapshots, the full directory name with UUID is accepted. Use -k and -tb options to override target keyspace/table if names differ.
The tool uses the directory names to determine the target keyspace and table:
# This path:/tmp/load/my_keyspace/my_table/nb-1-big-Data.db
# Loads into:# Keyspace: my_keyspace# Table: my_tableArguments
Section titled “Arguments”| Argument | Description |
|---|---|
dir_path | Path to directory containing SSTable files. Must follow <keyspace>/<table>/ structure. |
Options
Section titled “Options”Required Options
Section titled “Required Options”| Option | Description |
|---|---|
-d, --nodes <hosts> | Comma-separated list of initial hosts for ring discovery (required) |
Authentication Options
Section titled “Authentication Options”| Option | Description |
|---|---|
-u, --username <user> | Username for authentication |
-pw, --password <password> | Password for authentication |
-ap, --auth-provider <class> | Custom auth provider class |
-p, --port <port> | Native transport port (default: 9042) |
-sp, --storage-port <port> | Storage port for streaming (default: 7000) |
Performance Options
Section titled “Performance Options”| Option | Description |
|---|---|
--throttle-mib <MiB/s> | Throttle streaming speed in MiB per second |
--inter-dc-throttle-mib <MiB/s> | Throttle for inter-datacenter streaming |
--entire-sstable-throttle-mib <MiB/s> | Throttle for entire-SSTable streaming |
--entire-sstable-inter-dc-throttle-mib <MiB/s> | Inter-DC throttle for entire-SSTable streaming |
-cph, --connections-per-host <n> | Number of concurrent connections per host |
Target Override Options
Section titled “Target Override Options”| Option | Description |
|---|---|
-k, --target-keyspace <name> | Override target keyspace (different from directory name) |
-tb, --target-table <name> | Override target table (different from directory name) |
SSL/TLS Options
Section titled “SSL/TLS Options”| Option | Description |
|---|---|
-f, --conf-path <path> | Path to cassandra.yaml. Reads stream_throughput_outbound, client_encryption_options, and server_encryption_options |
--keystore <path> | Path to SSL keystore |
--keystore-password <pass> | Keystore password |
--truststore <path> | Path to SSL truststore |
--truststore-password <pass> | Truststore password |
--ssl-protocol <protocol> | SSL protocol (e.g., TLSv1.2) |
--ssl-ciphers <ciphers> | Comma-separated list of SSL ciphers |
Other Options
Section titled “Other Options”| Option | Description |
|---|---|
-i, --ignore <hosts> | Comma-separated list of hosts to ignore during streaming |
--no-progress | Suppress progress output |
-v, --verbose | Enable verbose output |
Examples
Section titled “Examples”Basic Usage
Section titled “Basic Usage”# Load SSTables into clustersstableloader -d 192.168.1.10,192.168.1.11 /tmp/restore/my_keyspace/my_table/With Authentication
Section titled “With Authentication”# Load with username/passwordsstableloader -d node1,node2,node3 \ -u cassandra \ -pw cassandra \ /backup/my_keyspace/users/With Throttling
Section titled “With Throttling”# Limit streaming to 100 MiB/s to prevent overwhelming the clustersstableloader -d node1,node2 \ --throttle-mib 100 \ /restore/my_keyspace/my_table/With SSL
Section titled “With SSL”# Method 1: Using cassandra.yaml for SSL settingssstableloader -d node1,node2 \ -f /etc/cassandra/cassandra.yaml \ /restore/my_keyspace/my_table/
# Method 2: Explicit SSL parameterssstableloader -d node1,node2 \ --keystore /path/to/keystore.jks \ --keystore-password secret \ --truststore /path/to/truststore.jks \ --truststore-password secret \ --ssl-protocol TLSv1.2 \ /restore/my_keyspace/my_table/Multiple Connections for Speed
Section titled “Multiple Connections for Speed”# Increase parallelism with more connections per hostsstableloader -d node1,node2,node3 \ --connections-per-host 8 \ /restore/my_keyspace/large_table/Ignore Specific Nodes
Section titled “Ignore Specific Nodes”# Skip streaming to a problematic nodesstableloader -d node1,node2,node3 \ -i node3 \ /restore/my_keyspace/my_table/Common Use Cases
Section titled “Common Use Cases”Restoring from Snapshot
Section titled “Restoring from Snapshot”#!/bin/bashSNAPSHOT_NAME="daily_backup"KEYSPACE="my_keyspace"TABLE="my_table"NODES="node1,node2,node3"RESTORE_DIR="/tmp/restore"
# 1. Create directory structuremkdir -p ${RESTORE_DIR}/${KEYSPACE}/${TABLE}
# 2. Copy snapshot files (from backup location)cp /backup/${SNAPSHOT_NAME}/${KEYSPACE}/${TABLE}/*.db \ ${RESTORE_DIR}/${KEYSPACE}/${TABLE}/
# 3. Verify schema exists in target clustercqlsh node1 -e "DESCRIBE TABLE ${KEYSPACE}.${TABLE};"
# 4. Load datasstableloader -d ${NODES} ${RESTORE_DIR}/${KEYSPACE}/${TABLE}/
# 5. Cleanuprm -rf ${RESTORE_DIR}Cross-Cluster Migration
Section titled “Cross-Cluster Migration”#!/bin/bashSOURCE_DATA="/var/lib/cassandra/data/old_keyspace/old_table-uuid"TARGET_KEYSPACE="new_keyspace"TARGET_TABLE="new_table"TARGET_NODES="newcluster1,newcluster2,newcluster3"STAGING="/tmp/migration"
# 1. Create staging directory with target keyspace/table namesmkdir -p ${STAGING}/${TARGET_KEYSPACE}/${TARGET_TABLE}
# 2. Copy SSTables (ensure table is not being compacted)nodetool flush old_keyspace old_tablecp ${SOURCE_DATA}/*Data.db ${STAGING}/${TARGET_KEYSPACE}/${TARGET_TABLE}/cp ${SOURCE_DATA}/*Index.db ${STAGING}/${TARGET_KEYSPACE}/${TARGET_TABLE}/cp ${SOURCE_DATA}/*Filter.db ${STAGING}/${TARGET_KEYSPACE}/${TARGET_TABLE}/cp ${SOURCE_DATA}/*Statistics.db ${STAGING}/${TARGET_KEYSPACE}/${TARGET_TABLE}/cp ${SOURCE_DATA}/*Summary.db ${STAGING}/${TARGET_KEYSPACE}/${TARGET_TABLE}/cp ${SOURCE_DATA}/*TOC.txt ${STAGING}/${TARGET_KEYSPACE}/${TARGET_TABLE}/cp ${SOURCE_DATA}/*CompressionInfo.db ${STAGING}/${TARGET_KEYSPACE}/${TARGET_TABLE}/ 2>/dev/nullcp ${SOURCE_DATA}/*Digest.crc32 ${STAGING}/${TARGET_KEYSPACE}/${TARGET_TABLE}/ 2>/dev/null
# 3. Load into target clustersstableloader -d ${TARGET_NODES} \ --throttle-mib 200 \ ${STAGING}/${TARGET_KEYSPACE}/${TARGET_TABLE}/
# 4. Verify row countecho "Source count:"cqlsh source_node -e "SELECT COUNT(*) FROM old_keyspace.old_table;"echo "Target count:"cqlsh newcluster1 -e "SELECT COUNT(*) FROM ${TARGET_KEYSPACE}.${TARGET_TABLE};"Loading Generated SSTables
Section titled “Loading Generated SSTables”When loading SSTables created by external tools (like Spark):
# SSTables must be in correct format and have matching schemasstableloader -d node1,node2,node3 \ --verbose \ /generated_data/my_keyspace/my_table/Schema Requirements
Section titled “Schema Requirements”Schema Must Exist First
The target keyspace and table must exist in the cluster before running sstableloader. The tool does not create schemas.
# Verify schema existscqlsh node1 -e "DESCRIBE KEYSPACE my_keyspace;"cqlsh node1 -e "DESCRIBE TABLE my_keyspace.my_table;"
# If restoring, recreate schema firstcqlsh node1 -f /backup/schema.cqlSchema Compatibility
Section titled “Schema Compatibility”The SSTable schema must be compatible with the target table schema:
| Scenario | Result |
|---|---|
| Exact schema match | Success |
| Target has additional columns | Success (new columns will be null) |
| Target missing columns | Failure |
| Different column types | Failure |
| Different primary key | Failure |
Performance Tuning
Section titled “Performance Tuning”Factors Affecting Speed
Section titled “Factors Affecting Speed”| Factor | Impact | Tuning |
|---|---|---|
| Network bandwidth | High | Use --throttle-mib to prevent saturation |
| Connections per host | Medium | Increase --connections-per-host |
| Cluster size | Medium | More nodes = parallel streaming |
| SSTable size | Low | Tool handles any size |
| Disk I/O on source | Medium | Use SSD for staging directory |
Recommended Settings by Scenario
Section titled “Recommended Settings by Scenario”Small dataset (< 10 GB):
sstableloader -d nodes /path/to/data/# Default settings usually sufficientMedium dataset (10-100 GB):
sstableloader -d nodes \ --connections-per-host 4 \ --throttle-mib 200 \ /path/to/data/Large dataset (> 100 GB):
sstableloader -d nodes \ --connections-per-host 8 \ --throttle-mib 500 \ /path/to/data/
# Consider loading during off-peak hours# Monitor cluster health during loadMonitoring Progress
Section titled “Monitoring Progress”Verbose Output
Section titled “Verbose Output”sstableloader -d nodes -v /path/to/data/
# Sample output:# Established connection to initial hosts# Opening sstables and calculating sections to stream# Streaming relevant part of /path/to/data/nb-1-big-Data.db to [/192.168.1.10, /192.168.1.11]# progress: [node1]0:0/1 0% [node2]0:0/1 0% total: 0% 0.0 MB/s# progress: [node1]0:1/1 100% [node2]0:1/1 100% total: 100% 45.2 MB/s# Summary statistics:# Connections per host: 1# Total files transferred: 2# Total bytes transferred: 156.3 MB# Total duration: 3.5 s# Average throughput: 44.7 MB/sMonitoring Cluster During Load
Section titled “Monitoring Cluster During Load”# On target nodes, watch streaming activitynodetool netstats
# Watch for compaction backlognodetool compactionstats
# Monitor load on target nodesnodetool tpstats | grep -i streamTroubleshooting
Section titled “Troubleshooting”Connection Refused
Section titled “Connection Refused”# Error: Failed to connect to node1:9042
# Check 1: Is Cassandra running on target nodes? (run on the target node via SSH)ssh node1 "nodetool status"
# Check 2: Is native transport enabled?ssh node1 "nodetool statusbinary"
# Check 3: Firewall allows port 9042?nc -zv node1 9042
# Check 4: Correct port specified?sstableloader -d node1 -p 9142 /path/ # If using non-default portAuthentication Failed
Section titled “Authentication Failed”# Error: Authentication error
# Verify credentials workcqlsh node1 -u username -p password
# Use correct authentication optionssstableloader -d node1 -u username -pw password /path/Schema Mismatch
Section titled “Schema Mismatch”# Error: Unknown keyspace/table
# Verify schema existscqlsh node1 -e "DESCRIBE KEYSPACE my_keyspace;"
# Check directory structure matches keyspace/table namesls /path/to/load/# Should show: my_keyspace/ls /path/to/load/my_keyspace/# Should show: my_table/SSL Errors
Section titled “SSL Errors”# Error: SSL handshake failed
# Method 1: Use cassandra.yaml with SSL configsstableloader -d node1 -f /etc/cassandra/cassandra.yaml /path/
# Method 2: Verify keystore/truststorekeytool -list -keystore /path/to/keystore.jks
# Method 3: Check SSL protocol compatibilitysstableloader -d node1 \ --ssl-protocol TLSv1.2 \ --keystore /path/to/keystore.jks \ --keystore-password pass \ --truststore /path/to/truststore.jks \ --truststore-password pass \ /path/Streaming Timeout
Section titled “Streaming Timeout”# Error: Streaming timed out
# Reduce throughput to prevent overwhelming nodessstableloader -d nodes --throttle-mib 50 /path/
# Check cluster health (run on the target node via SSH)ssh node1 "nodetool status"ssh node1 "nodetool tpstats"Incomplete Files
Section titled “Incomplete Files”# Error: Missing component files
# Verify all SSTable components presentls /path/to/keyspace/table/# Need at minimum: Data.db, Index.db, Filter.db, Statistics.db, Summary.db, TOC.txt
# Copy all components for each SSTablecp /source/*-1-big-* /dest/Best Practices
Section titled “Best Practices”sstableloader Guidelines
- Verify schema first - Table must exist before loading
- Use throttling - Prevent overwhelming target cluster
- Monitor during load - Watch cluster health metrics
- Load during off-peak - Reduce impact on production traffic
- Verify after loading - Check row counts and sample data
- Clean staging directory - Remove copied SSTables after successful load
- Consider repair - Run repair after large data loads for consistency
Cautions
- Does not create keyspace or table schemas
- Source files are not deleted after loading
- Large loads can impact cluster performance
- Authentication credentials in command line may be visible in process lists
Related Commands
Section titled “Related Commands”| Command | Relationship |
|---|---|
| nodetool snapshot | Create snapshots for loading |
| nodetool refresh | Alternative for loading local SSTables |
| nodetool import | Import SSTables from directory |
| nodetool netstats | Monitor streaming progress |
| sstableutil | List SSTable files |