| 1 | # redis-copy.rb - Copyright (C) 2009-2010 Salvatore Sanfilippo |
| 2 | # BSD license, See the COPYING file for more information. |
| 3 | # |
| 4 | # Copy the whole dataset from one Redis instance to another one |
| 5 | # |
| 6 | # WARNING: currently hashes and sorted sets are not supported! This |
| 7 | # program should be updated. |
| 8 | |
| 9 | require 'rubygems' |
| 10 | require 'redis' |
| 11 | require 'digest/sha1' |
| 12 | |
| 13 | def redisCopy(opts={}) |
| 14 | sha1="" |
| 15 | src = Redis.new(:host => opts[:srchost], :port => opts[:srcport]) |
| 16 | dst = Redis.new(:host => opts[:dsthost], :port => opts[:dstport]) |
| 17 | puts "Loading key names..." |
| 18 | keys = src.keys('*') |
| 19 | puts "Copying #{keys.length} keys..." |
| 20 | c = 0 |
| 21 | keys.each{|k| |
| 22 | vtype = src.type?(k) |
| 23 | ttl = src.ttl(k).to_i if vtype != "none" |
| 24 | |
| 25 | if vtype == "string" |
| 26 | dst[k] = src[k] |
| 27 | elsif vtype == "list" |
| 28 | list = src.lrange(k,0,-1) |
| 29 | if list.length == 0 |
| 30 | # Empty list special case |
| 31 | dst.lpush(k,"") |
| 32 | dst.lpop(k) |
| 33 | else |
| 34 | list.each{|ele| |
| 35 | dst.rpush(k,ele) |
| 36 | } |
| 37 | end |
| 38 | elsif vtype == "set" |
| 39 | set = src.smembers(k) |
| 40 | if set.length == 0 |
| 41 | # Empty set special case |
| 42 | dst.sadd(k,"") |
| 43 | dst.srem(k,"") |
| 44 | else |
| 45 | set.each{|ele| |
| 46 | dst.sadd(k,ele) |
| 47 | } |
| 48 | end |
| 49 | elsif vtype == "none" |
| 50 | puts "WARNING: key '#{k}' was removed in the meanwhile." |
| 51 | end |
| 52 | |
| 53 | # Handle keys with an expire time set |
| 54 | if ttl != -1 and vtype != "none" |
| 55 | dst.expire(k,ttl) |
| 56 | end |
| 57 | |
| 58 | c = c+1 |
| 59 | if (c % 1000) == 0 |
| 60 | puts "#{c}/#{keys.length} completed" |
| 61 | end |
| 62 | } |
| 63 | puts "DONE!" |
| 64 | end |
| 65 | |
| 66 | if ARGV.length != 4 |
| 67 | puts "Usage: redis-copy.rb <srchost> <srcport> <dsthost> <dstport>" |
| 68 | exit 1 |
| 69 | end |
| 70 | puts "WARNING: it's up to you to FLUSHDB the destination host before to continue, press any key when ready." |
| 71 | STDIN.gets |
| 72 | srchost = ARGV[0] |
| 73 | srcport = ARGV[1] |
| 74 | dsthost = ARGV[2] |
| 75 | dstport = ARGV[3] |
| 76 | puts "Copying #{srchost}:#{srcport} into #{dsthost}:#{dstport}" |
| 77 | redisCopy(:srchost => srchost, :srcport => srcport.to_i, |
| 78 | :dsthost => dsthost, :dstport => dstport.to_i) |