最近开发的一个项目中,有一个需求,需要将内部现有的PG数据库中两张表中的数据同步到外部服务器的redis中去,而且以后每天都要形成一个增量的数据写入到外网的redis中,我尝试了两种方法:

1、直接通过PHP读取数据,循环的写入到Redis中去
2、使用redis-cli --pipe的方式写入

    申明:外网不能访问内部的任何机器,两个表中的数据量有千万的数量级

方法一:PHP读取数据库写入到redis的方式

    由于数据量比较大,一次查询出所有的数据写入到redis是不可能的,直接导致内存溢出,所以不得不根据id排序,然后通过偏移量一次查询3000多条,然后写入到redis中,最后在写入过程中我发现写入的速度太慢了,如果把这些数据全导入进去,我得耗费一天的时间;然后果断放弃了这个方法,采用了第二个方法

 

方法二:使用redis-cli --pipe的方式

    首先介绍一下:这个命令从redis 2.4.14的版本后出现的,也是官方推荐的批量数据的导入方式,只要按照格式将需要导入的数据写入文件,直接在Linux上执行:

cat dataredis.txt | redis-cli --pipe

即可快速的导入数据,官方文档说明:http://www.redis.cn/topics/pipelining.html

    dataredis.txt文件中数据的存放格式要求比较严格,换行符必须使用“\r\n”,数据格式如图:Postgres到redis的数据迁移_redis

数据内容的解释:

*3                        #表示有三个参数:SET blog_url gzinfo.blog.51cto.com
$3                        #对第一个参数SET计算长度得到的值
SET                       #redis的执行数据操作的命令
$8                        #对第二个参数(blog_url)计算得到的长度
blog_url                  #存放数据的KEY  
$21                       #对第三个参数计算得到的长度
gzinfo.blog.51cto.com     #KEY对应的value值

 

下面给出在PG中导入pipe数据的shell脚本:

#!/bin/bash
# 增量导出昨日新增的数据
yestday=$(date -d '-1 day' +'%Y%m%d')
psql -h 127.0.0.1 -Usqluser -d testdb -t -A -c "SELECT '*3'||chr(10)||'$'||LENGTH('SET')||chr(10)||'SET'||chr(10)||'$'||LENGTH (trim( both chr(10)||chr(13) FROM key))||chr(10)||trim( both chr(10)||chr(13) FROM key)||chr(10)||'$'||LENGTH (trim( both chr(10)||chr(13) FROM value ))||chr(10)||trim( both chr(10)||chr(13) FROM value )||chr(10) FROM tbtest where sample_type='7' AND record_time_int='${yestday}'" >>format2redis.txt
# 转换文件格式
unix2dos format2redis.txt

这里,我们在linux上先导出以“\n”换行的文件,然后再转换windows下面的换行符,然后将formart2redis.txt上传到外网服务器,直接执行:

cat format2redis.txt|redis-cli --pipe

经过测试,160多万的数据基本上5秒内导入完成