Jirene
Jirene

Reputation: 151

It is possible to merge two separate DBs (e.g. db0, db1) running in one single Redis instance (6379) into one single DB (db0)?

Cannot find an easy solution. Migrate command seems not to be the solution. Persist, delete them, create one single db and load the backup maybe?

Upvotes: 1

Views: 774

Answers (1)

LeoMurillo
LeoMurillo

Reputation: 6754

There is the SWAPDB that allows you to swap them.

There is no out-of-the-box support for merging, since there may be conflicts. If there are two keys with the same name on both databases, it needs to be resolved.

The MOVE commands allows you to move a key from the current DB to a destination DB.

You can use a combination of SCAN and MOVE to get the merge done. I suggest SCAN instead of KEYS because if you're doing this in production, you don't want to block the server for long periods of time.

Here a Lua script to do this:

local result = redis.call('SCAN', ARGV[1])
local conflict = {}
local moved = {}
for _,key in ipairs(result[2]) do
    if redis.call('MOVE', key, ARGV[2]) == 0 then
        table.insert(conflict, key)
    else
        table.insert(moved, key)
    end
end
result[2] = conflict
result[3] = moved
return result

You call this with parameters:

  • numkeys: 0
  • ARGV[1]: the cursor for SCAN, initially 0.
  • ARGV[2]: the destination database. E.g. 2

Make sure to SELECT the source database first.

Here a example first run:

> EVAL "local result = redis.call('SCAN', ARGV[1]) \n local conflict = {} \n local moved = {} \n for _,key in ipairs(result[2]) do \n     if redis.call('MOVE', key, ARGV[2]) == 0 then \n         table.insert(conflict, key) \n else \n     table.insert(moved, key) \n     end \n end \n result[2] = conflict \n result[3] = moved \n return result" 0 0 2
1) "56"
2) 1) "key:6"
3) 1) "key:79"
   2) "key:96"
   3) "key:44"
   4) "key:91"
   5) "key:82"
   6) "key:25"
   7) "key:22"
   8) "key:41"
   9) "key:73"

Here the SCAN found 10 keys, returned next cursor 56. key:6 was found on the destination, so it was not moved. The third entry is the list of keys actually moved.

As with SCAN, you need to call multiple times until the return cursor is 0. And remember added keys in between SCAN calls may or may not be returned.

You can modify the Lua script to:

  • Implement your merge logic, like delete the key on the destination and then move, and still report the deleted key on the destination separately.
  • Change SCAN to use a larger COUNT if you want more keys covered by call.
  • Replace SCAN with KEYS to do it on one go.

Upvotes: 3

Related Questions