最近开发的一个项目中,有一个需求,需要将内部现有的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”,数据格式如图:
数据内容的解释:
*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秒内导入完成