Featured image of post Redis Migration Script

Redis Migration Script

A script for migrating Redis databases between servers

Old Method

Sometimes you need to migrate data from one Redis server to another, or between other databases. Previously, I could transfer data from a server only through a full backup, but this does not allow for migrating data between bases. Here is the algorithm.

  1. Enter into the original Redis and make Save
1
2
3
REDISCLI_AUTH="password" 
redis-cli CONFIG GET DIR
redis-cli SAVE

The first command will print the path to the directory where the dump will be stored.

  1. Add arguments to the target Redis to disable AppendOnly and restart it
1
2
--dbfilename dump.rdb
--appendonly no
  1. Copy the dump to the target Redis and execute its loading
1
2
REDISCLI_AUTH="password" 
redis-cli BGREWRITEAOF
  1. Move the target Redis to the AppendOnly mode by removing previously added keys

Why migrate data between bases?

In my old cluster, I had two services, each with their own Redis server. In any Redis there are 16 default databases, why not use #0 for service A and #2 for service B? Here you hit into the migration problem from base to base.

New Method

Based on MIGRATE. The script is presented below. Its advantages are also.

  1. can migrate between bases
  2. no need to restart Redis
  3. no need to copy backups
  4. There is a check after transferring by calculating the hash sum considering both key contents
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#!/usr/bin/env sh
set -e

SRC_HOSTNAME='source-redis-hostname'
SRC_PORT='6379'
SRC_PASSWORD='password'
SRC_DATABASE='0'
DEST_HOSTNAME='destination-redis-hostname'
DEST_PORT='6379'
DEST_PASSWORD='password'
DEST_DATABASE='1'

main() {
  migrate | xargs -0 printf 'migration status: %s'
  CHECKSUM="$(mktemp)"
  hash --no-auth-warning -h "${SRC_HOSTNAME}" -p "${SRC_PORT}" \
    -a "${SRC_PASSWORD}" -n "${SRC_DATABASE}" | tee "${CHECKSUM}" | xargs -0 printf 'source checksum: %s'
  CHECKSUM_VERIFY="${CHECKSUM}" hash --no-auth-warning -h "${DEST_HOSTNAME}" -p "${DEST_PORT}" \
    -a "${DEST_PASSWORD}" -n "${DEST_DATABASE}" | xargs -0 printf 'target checksum validation: %s'
  rm -f "${CHECKSUM}"
}

hash() {
  EXTRA_ARGS="${@}"
  redis-cli ${EXTRA_ARGS} --raw --scan | \
  sed -r 's/"/\\"/g; s/^(.+)$/GET "\1"/g;' | \
  redis-cli ${EXTRA_ARGS} | sort | \
  if [ -f "${CHECKSUM_VERIFY}" ]; then
    sha256sum -c "${CHECKSUM_VERIFY}"
  else
    sha256sum -
  fi
}

migrate() {
  AUTH="--no-auth-warning -h ${SRC_HOSTNAME} -p ${SRC_PORT} -a ${SRC_PASSWORD} -n ${SRC_DATABASE}"
  redis-cli ${AUTH} --raw --scan | \
  tr '\n' '\0' | \
  xargs -0 redis-cli ${AUTH} \
    MIGRATE "${DEST_HOSTNAME}" "${DEST_PORT}" "" "${DEST_DATABASE}" 5000 \
    COPY REPLACE AUTH "${DEST_PASSWORD}" KEYS
}

main
Licensed under Apache License, Version 2.0
Last updated on Oct 17, 2024 12:47 +0300
All rights reserved
Built with Hugo
Theme Stack designed by Jimmy