Старый способ ¶
Иногда нужно мигрировать данные из одного Redis в другой, или между базами другого. Ранее, я мог перенести данные с сервера на сервер только через полный бекап, но это не позволяет мигрировать данные между базами. Всё равно, приведу здесь этот алгоритм.
- Зайти в исходный Redis и сделать Save
1
2
3
| REDISCLI_AUTH="password"
redis-cli CONFIG GET DIR
redis-cli SAVE
|
Первая команда выведет путь к папке, где будет лежать дамп.
- Добавить к целевому Redis аргументы для отключения AppendOnly и перезапустить его
1
2
| --dbfilename dump.rdb
--appendonly no
|
- Скопировать дамп в целевой Redis и выполнить его загрузку
1
2
| REDISCLI_AUTH="password"
redis-cli BGREWRITEAOF
|
- Перевести целевой Redis в AppendOnly режим убрав ранее добавленные ключи
Зачем мигрировать данные между базами?
В старом кластере у меня два сервиса, у каждого свой Redis. В любом Redis есть по умолчанию 16 баз, почему бы не использовать №0 для сервиса А и №2 - для сервиса Б? Вот тут то ты и сталкиваешься с задачей миграции из базы в базу.
Новый способ ¶
Основан на MIGRATE. Скрипт представлен ниже. Преимущества этого способа - тоже.
- Можно мигрировать между базами
- Не нужно перезапускать Redis-ы
- Не нужно копировать бекапы
- Есть проверка после переноса путём вычисления хеш суммы учитывая так же и содержимое ключей
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
|