Gih's Blog

只言片语

A better way to backup redis' rdb snapshot.

2014-07-20 by gihnius, tagged as redis

I first post a relate article here: http://www.qufor.com/topics/529999c87cc1f87c30000004

Here is an update.

Basically, you can directly copy the file to a safe place, here is the redis document about persistence: http://redis.io/topics/persistence

Redis is very data backup friendly since you can copy RDB files while the database is running: the RDB is never modified once produced, and while it gets produced it uses a temporary name and is renamed into its final destination atomically using rename(2) only when the new snapshot is complete.

You can get the persistence info by running this command: 

echo 'info Persistence' | redis-cli 

You will get an output like the following

# Persistence
loading:0
rdb_changes_since_last_save:6
rdb_bgsave_in_progress:0
rdb_last_save_time:1406022719
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:0
rdb_current_bgsave_time_sec:-1
aof_enabled:0
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:-1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok

See these lines: rdb_bgsave_in_progress:0 and rdb_last_bgsave_status:ok. Why I need to verify the bgsave status?

By default redis save the dataset every N seconds if there are at least M changes in the dataset, this can be changed from configuration:

save 60 1000

if redis data is changed very frequent, I'd like to get the latest snapshot, so I'd run bgsave before copying rdb file by this command:

echo bgsave | redis-cli

So here is the finally script to do the backup:

#!/bin/bash

## simple redis rdb backup script
## usage
## rdb-backup.sh rdb.path backup.dir bgsave.wait.seconds

rdb=${1:-"/var/db/redis/dump.rdb"}

backup_to=${2:-"/data/backup/redis/"}

wait=${3:-10} ## default wait for 10 seconds

test -f "$rdb" || {
    echo No rdb file found ; exit 1
}
test -d "$backup_to" || {
    echo Creating backup directory $backup_to && mkdir -p "$backup_to"
}

## launch bgsave
echo bgsave | redis-cli
echo "waiting for $wait seconds..."
sleep $wait
try=5
while [ $try -gt 0 ] ; do
    saved=$(echo 'info Persistence' | redis-cli | awk '/rdb_bgsave_in_progress:0/{print "saved"}')
    ok=$(echo 'info Persistence' | redis-cli | awk '/rdb_last_bgsave_status:ok/{print "ok"}')
    if [[ "$saved" = "saved" ]] && [[ "$ok" = "ok" ]] ; then
        cp "$rdb" "$backup_to"
        if [ $? = 0 ] ; then
            echo "redis rdb $rdb copied to $backup_to ."
            exit 0
        else 
            echo ">> Failed to copy $rdb to $backup_to !"
        fi
    fi
    try=$((try - 1))
    echo "redis maybe busy, waiting and retry in 5s..."
    sleep 5
done
exit 1

Available on github: https://github.com/gihnius/rdb-backup