MySQL数据导入Redis小记

来源:互联网 发布:手机淘宝千牛怎么用 编辑:程序博客网 时间:2024/05/01 06:01

最近在做一些MySQL + Redis结合的工作,其中涉及到了MySQL的数据迁移到Redis的东西,小记一下。

首先,截止2016.11.21,我在Windows环境下都无法用Redis-cli.exe利用pipeline批量插入数据。原因大概是因为字符串等各种格式的问题,同样的命令在Ubuntu的终端下运行良好。Redis版本是Windows开源团队的Redis-x64-3.2.100。地址是MSOpenTech\Redis。

Redis 在Windows中的服务端是可以变为Windows服务自启动的,具体命令如下:

redis-server --service-install redis.windows.conf

安装完之后不会自启动,但是可以调用下面命令来进行启动。

redis-server --service-start

导入初期我是直接写了个工具,遍历了MySQL中的所有数据然后插入Redis的,我选择了直接用C#写一个控制台程序,选用的客户端是StackExchange.Redis,然后利用各类的Async进行异步操作(实际上就是使用pipeline),速度还是比较可以的。

后面发布的时候找了一下,Redis本身的客户端可以也利用pipeline来进行批量插入(Mass Insertiong),官方文档(Redis Mass Insertion
h)[http://redis.io/topics/mass-insert],然后结合pipeline,就可以利用脚本将MySQL中的数据转换为Redis-cli可以识别的格式,直接批量插入即可。

在文中,作者给出了示例,用如下的格式进行格式化输入即可:

*<args><cr><lf>$<len><cr><lf><arg0><cr><lf><arg1><cr><lf>...<argN><cr><lf># Where <cr> means "\r" (or ASCII character 13) and <lf> means "\n" (or ASCII character 10).

举个简单的例子,如果要插入一个String类型的key-value值,那么就是

*3\r\n    #表明命令中包含的参数个数$3\r\n    #表明第一个参数的长度SET\r\n   #第一个参数,注意各项关键字也都是参数,如这里的SET$3\r\n    #表明第二个参数的长度123\r\n   #第二个参数$4\r\n    #表明第三个参数的长度4567\r\n  #第三个参数

执行完毕的结果就是插入一个key为123,Value为4567的String类型的Key-Value啦。

而这里涉及到的一个东西就是Redis的Protocol,具体可以查看这里Redis Protocol specification。我也是从这里知道了到底上面那串命令的含义,以及如何处理数据库中空的列的数据。(卖个关子)

我参考了这篇文章
浅谈 Redis 与 MySQL 的耦合性以及利用管道完成 MySQL 到 Redis 的高效迁移 ,里面有讲到如何利用SQL语句将需要的数据格式化成为Redis-cli可以识别的格式,实际上只要两行代码就解决了问题,非常简单。
文章里面展示了这两句核心代码:

# 这是SQL语句,格式化数据用cat mysql_to_redis.sql SELECT CONCAT(  "*4\r\n",  \'$\', LENGTH(redis_cmd), \'\r\n\',  redis_cmd, \'\r\n\',  \'$\', LENGTH(redis_key), \'\r\n\',  redis_key, \'\r\n\',  \'$\', LENGTH(hkey), \'\r\n\',  hkey, \'\r\n\',  \'$\', LENGTH(hval), \'\r\n\',  hval, \'\r\')FROM (  SELECT  \'HSET\' AS redis_cmd,  \'david\' AS redis_key,  myname AS hkey,  mymoney AS hval  FROM david_lin) AS t;
#这是命令行/终端语句, 直接执行就可以导入啦mysql -uroot -poracle test --skip-column-names --raw < mysql_to_redis.sql | redis-cli --pipe

只要简单执行上述的两行代码,就可以直接迁移。
然而在我的使用过程中发现了一个问题,由于业务关系,我的基础业务数据库中会存在空列,而这个又是关键数据,需要迁移到Redis中的。单纯利用上述的SQL语句,进行操作的时候,Redis-cli会抛出“Unknown Command NULL on Redis.”
我们知道,Redis是可以存储二进制数据的(而实际上Redis存储的Value都是二进制格式存储的),所以空数据理论上是可以存入的。然而根据观察,Redis的空数据,表现为空字符串形式,即。所以,我们需要将我们数据库中为NULL的数据,转换成为”进行输出。
而Redis-cli接受空字符串的时候,是可以根据参数长度进行判断的。具体表现为“$0\r\n\r\n”,正好一致。

所以上述的命令应该修改为如下:

cat mysql_to_redis.sql SELECT CONCAT(  "*4\r\n",  \'$\', LENGTH(redis_cmd), \'\r\n\',  redis_cmd, \'\r\n\',  \'$\', LENGTH(redis_key), \'\r\n\',  redis_key, \'\r\n\',  \'$\', LENGTH(hkey), \'\r\n\',  hkey, \'\r\n\',  \'$\', LENGTH(hval), \'\r\n\',  hval, \'\r\')FROM (  SELECT  \'HSET\' AS redis_cmd,  \'david\' AS redis_key,  myname AS hkey,  if(mymoney is not null, mymoney, '') AS hval  FROM david_lin) AS t;

看出来区别了吗~ 因为NULL数据长度肯定为0,所以上面一部分不需要修改,只需要修改下面的SELECT语句即可。

这样就可以将带有空行的数据也一次导入啦~!

另外需要注意的是,上述终端命令需要根据自己的实际情况,将数据库所在的ip和端口等都填上哦。

0 0
原创粉丝点击