将Redis的数据加载到CircleCI中
- (追記1) s3cmd signがうまく動かない事があったので、sign用のスクリプトを書いた
开场白
我开始使用CircleCI,但是在我的现有项目中,我们使用Redis来存储类似地址数据之类的常量数据,所以在测试之前必须加载这些数据,否则无法正常运行。但是在阅读了CircleCI的文档后,发现没有特别推荐的方法,所以我决定自己来创建。
我本来想直接替换dump.rdb文件,但因为其中包含了很多缓存和不需要进行测试的数据而导致文件过于庞大,所以这次决定只设置必要的数据到CircleCI中。
另外,由于不希望将大型二进制数据上传到GitHub,所以选择使用S3进行数据交换。
Redis数据的导入/导出
在寻找REDIS的导入/导出资料时,我发现只有”让我们替换RDB文件吧”这样的说法,让我很困扰。但是后来我找到了一个好的解决办法。
以下是两个链接:
1. https://github.com/sripathikrishnan/redis-rdb-tools
2. http://redis.io/topics/mass-insert
通过将REDIS的二进制协议数据导出,并使用redis-cli流式传输到REDIS,这就是我们所需要的。听起来不错。
在文本协议示例中,参考链接为 http://uokada.hatenablog.jp/entry/2012/12/01/021131 。由于此次使用的数据包含二进制数据,因此该示例不适用。
今回作ったスクリプトはこちら https://gist.github.com/shnjp/886eda28061c37047cd5
出口
首先,为了安全起见,在Redis中执行bgsave操作。
basetimestamp=`redis-cli lastsave`
redis-cli bgsave
while [ 1 ]
do
curtimestamp=`redis-cli lastsave`
if [ $basetimestamp != $curtimestamp ]
then
break
fi
sleep 1
done
只需将必要的数据转换成二进制协议并进行gzip压缩。
rdb --command protocol --key KEY-PATTERN $REDIS_DUMP_RDB gzip --stdout > $REDIS_PROTOCOL_FILE
将s3cmd用于向S3发送数据
s3cmd -c S3-CONFIG-FILE put $REDIS_PROTOCOL_FILE $S3_BACKUP_BUCKET
进口
可以使用curl将导入的数据发送到redis-cli,但是为了从CircleCI获取数据,需要使用S3的一次性令牌生成URL。
在这个链接中我参考了 https://github.com/hajoeichler/s3cmd-signed-url/blob/master/s3cmd-signed-url ,只写了必要的部分 https://gist.github.com/shnjp/886eda28061c37047cd5#file-get_s3_object-sh
由于无法确定时间戳的值引发了签名错误的问题,所以我用boto进行了重写。
#!/usr/bin/env python
"""
s3sign.py [ACCESS KEY] [SECRET KEY] [BUCKET] [KEY]
"""
import sys
from boto.s3.connection import S3Connection
access_key, secret_key, bucket_name, key_name = sys.argv[1:5]
connection = S3Connection(aws_access_key_id=access_key, aws_secret_access_key=secret_key)
key = connection.get_bucket(bucket_name).get_key(key_name)
print key.generate_url(600)
创建这样的脚本,并放在circle.yml中。
database:
post:
- curl `./s3sign.py S3-ACCESS-KEY S3-SECRET-KEY S3-BUCKET-NAME redis-cache-data.raw.gz` | gunzip | redis-cli --pipe
我添加了这样的内容。
不知道该吹捧什么地方
因为我从来没有很多机会编写过Shell脚本,所以遇到了很多困难。
回声规范
哎呀,原来 echo 命令的规则不同啊。没有 echo -e 真是让我很苦恼。
redis-rdb-tools无法处理二进制数据。
我遇到了一个问题,redis-rdb-tools只能识别utf-8编码,当我想将其转换为二进制协议时出错了。我写了一个补丁,解决了这个问题。