我想要还原过期的Redis数据并进行测试

我想要恢复和测试之前获取的Redis的RDB文件。

Redis配置文件的设置(摘录)

数据库文件名为dump.rdb,
目录为/usr/local/var/db/redis/。

普通地恢复

# バックアップ
mv /usr/local/var/db/redis/dump.rdb /usr/local/var/db/redis/dump.rdb.bk
# 前に取得したrdbファイルをコピーして上書き。
cp -i /path/to/backup/rdb/dump.rdb /usr/local/var/db/redis/
# Redis起動
redis-server /path/to/conf/redis.conf

結果- 事实纯属巧合

在数据加载时,过期的数据将被删除。。。。
尽管进行了各种调查研究,但没有找到Redis本身可以恢复过期数据的方法。

躲避策略

    1. 将系统时间还原至备份时间并进行恢复。

 

    读取rdb文件并转换为json格式,然后重新存入。

将系统时间回溯至进行备份的时间点,并进行恢复。

システム時刻を変更してから、普通にリストアする。
リストア自体はうまくいくが、時刻の設定変えると他のアプリに影響でそうなので不採用。

将rdb文件读取并转换为json,然后再将其重新存入。

使用以下工具:
https://github.com/sripathikrishnan/redis-rdb-tools

安装

pip install rdb-tools

将其转换为JSON

rdb-tools 有一个 bug。如果指定了 -f 参数,过滤条件就会被禁用。
不指定 -f 参数时,可以进行重定向。

# 全体で取得した結果にDB番号が入ってないのでDBを指定して出力。
rdb --command json --db 1 /path/to/backup/rdb/dump.rdb > /path/to/output/dump.json

这将全部被输出出来。

# 全体で取得した結果にDB番号が入ってない(はず。。)、なのでDBを指定して出力。
rdb --command json --db 1 -f /path/to/output/dump.json /path/to/backup/rdb/dump.rdb

将数据导入Redis

由于rdb-tools没有提供此功能,因此需要自己编写。

#!/usr/bin/python
import json
import redis
import argparse

class Callbacks(object):

    @staticmethod
    def zaddCallback(key, values, client):
        for value, score in values.items():
            client.zadd(key, value, score)

    @staticmethod
    def saddCallback(key, values, client):
        print "Key:{0}, Values:{1}".format(key, values)
        client.sadd(key, values)


class RedisRdbJsonLoader(object):

    def __init__(self, host, port, callback, timeout_sec=5):
        self.host = host
        self.port = port
        self.callback = callback
        self.timeout_sec = timeout_sec

    def load(self, rdb_json_file, given_db_num=None):
        rdb_json = json.load(rdb_json_file)
        if given_db_num is None:
            self.__load_to_each_db(rdb_json)
        else:
            self.__load_to_db(given_db_num, rdb_json[given_db_num])

    def __load_to_each_db(self, rdb_json):
        # rdb_json_file includes data in order of db num.
        for db_num, db_values in enumerate(rdb_json):
            self.__load_to_db(db_num, db_values)

    def __load_to_db(self, db_num, db_values):
        print "===================="
        print "Load value for db {0}".format(db_num)

        client = self.__get_redis_client(db_num)
        count = 0
        for key, values in db_values.items():
            self.callback(key, values, client)
            count += 1
            print "{0}:Value loaded for key {1}".format(count, key)


    def __get_redis_client(self, db_num):
        return redis.Redis(self.host, self.port, db_num, socket_timeout=self.timeout_sec)

__TYPE_ACTION_MAPPING = {
    # 'string': setCallback,
    # 'list': lpushCallback,
    'set': Callbacks.saddCallback,
    'zset': Callbacks.zaddCallback,
    # 'hash': hsetCallback
}

def get_parser():
    parser = argparse.ArgumentParser(description='Load Jsonized rdis *.rdb file into redis server.')
    parser.add_argument('-H', '--host', help="Hostname of Redis server.", default='localhost')
    parser.add_argument('-p', '--port', help="Port number of Redis server.", default=6379, type=int)
    parser.add_argument('-n', '--db_num', help="Target DB of Redis server to load data. if this value was given, only first element of json data will be used.", default=None, type=int)
    parser.add_argument('-f', '--data_file', help="Path to data file.", required=True, type=argparse.FileType('r'))
    parser.add_argument('-t', '--data_type', help="Redis type to load.", default='zset', choices=__TYPE_ACTION_MAPPING.keys())
    parser.add_argument('--timeout_sec', help="Redis timeout sec.", default=5, type=int)
    return parser


def execute(args):
    with args.data_file as file:
        callback = __TYPE_ACTION_MAPPING[args.data_type]
        RedisRdbJsonLoader(args.host, args.port, callback, args.timeout_sec).load(file, args.db_num)

if __name__ == '__main__':
    execute(get_parser().parse_args())

执行导入操作

如果只导入特定的数据库。

python load_rdb_json.py -n 1 -f /path/to/output/dump.json

如果要全部导入的话

python load_rdb_json.py -f /path/to/output/dump.json

結束了

广告
将在 10 秒后关闭
bannerAds