我想要还原过期的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本身可以恢复过期数据的方法。
躲避策略
-
- 将系统时间还原至备份时间并进行恢复。
- 读取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