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.
- 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.
- Add arguments to the target Redis to disable AppendOnly and restart it
1
2
| --dbfilename dump.rdb
--appendonly no
|
- Copy the dump to the target Redis and execute its loading
1
2
| REDISCLI_AUTH="password"
redis-cli BGREWRITEAOF
|
- 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.
- can migrate between bases
- no need to restart Redis
- no need to copy backups
- 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
|