Batch Rename Keys

redis

Solution

The solution:

Ok, here's the script I wrote to solve this problem. It requires the "Redis" gem. Hopefully someone else finds this useful...

#!/usr/bin/env ruby

# A script to translate the current redis database into a namespace for another environment
# GWI's Redis keys are namespaced as "datamine::production", "datamine::development", etc.
# This script connects to redis and translates these key names in-place.
#
# This script does not use Rails, but needs the "redis" gem available
require 'Benchmark'
require 'Redis'

FROM_NAMESPACE = "production"
TO_NAMESPACE = "development"
NAMESPACE_PREFIX = "datamine::"
REDIS_SERVER = "localhost"
REDIS_PORT   = "6379"
REDIS_DBS = [0,1,2,3,4,5]

redis = Redis.new(host: REDIS_SERVER, port: REDIS_PORT, timeout: 30)

REDIS_DBS.each do |redis_db|
  redis.select(redis_db)
  puts "Translating db ##{redis_db}..."
  seconds = Benchmark.realtime do
    dbsize = redis.dbsize.to_f
    inc_threshold = (dbsize/100.0).round
    i = 0
    old_keys = redis.keys("#{NAMESPACE_PREFIX}#{FROM_NAMESPACE}*")
    old_keys.each do |old_key|
      new_key = old_key.gsub(FROM_NAMESPACE, TO_NAMESPACE)
      redis.rename(old_key, new_key)
      print "#{((i/dbsize)*100.0).round}% complete\r" if (i % inc_threshold == 0) # on whole # % only
      i += 1
    end
  end
  puts "\nDone. It took #{seconds} seconds"
end

Problem

I have a rather large database (5 dbs of about a million keys each), and each key has the environment namespace in it. For example: `"datamine::production::crosswalk==foobar"` I need to sync my development environment with this data copied from the production RDB snapshot. So what I'm trying to do is batch rename every key, changing the namespace from `datamine::production` to `datamine::development`. Is there a good, way to achieve this? What I've tried so far redis-cli command of `keys "datamine::production*"`, piped into sed, then back to `redis-cli`. This takes forever, and bombs for some reason on many keys (combining several in the same line, sporadically). I'd prefer a better option. Perl search/replace on the .rdb file. My local redis-server flat refuses to load the modified RDB.

Original source