简介
通过pipe将MySQL数据批量导入Redis,自Redis 2.6以上版本起,Redis支持快速大批量导入数据,即官网的Redis Mass Insertion,即Pipe传输,
现在的业务场景是将mysql中某张表的所有数据传输到redis中存储起来。
大致思路是用MySql的concat()方法将查询出来的数据按照resp协议的格式拼接成redis命令集合,再通过redis-cli --pipe批量执行命令
redis存储设计
假设数据库为test,表结构如下:
create database if not exists test;
use test;
CREATE TABLE person (
id int(10) unsigned NOT NULL AUTO_INCREMENT,
name varchar(200) NOT NULL,
age varchar(200) NOT NULL,
PRIMARY KEY (id)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
考虑用hash来对mysql数据库的数据进行存储,每条数据库记录对应一条hash存储,表名+主键值为key值,列名为field值,value为对应的列值
这里使用的是HMSET命令,格式如下:
HMSET ‘person:id值’ field1 “Hello” field2 “World” 至于这个命令的resp格式,可以参照另外一篇文章resp
sql脚本
特别注意:因为RESP协议中的分隔符为在Linux下是\r\n,而在Windows下则为\n
Linux下的命令为:
SELECT CONCAT(
“*8\r\n”,
‘$’,LENGTH(redis_cmd),’\r\n’,redis_cmd,’\r\n’,
‘$’,LENGTH(redis_key),’\r\n’,redis_key,’\r\n’,
‘KaTeX parse error: Can't use function '\r' in math mode at position 18: …LENGTH(hkey1),'\̲r̲\n',hkey1,'\r\n…’,LENGTH(hval1),’\r\n’,hval1,’\r\n’,
‘KaTeX parse error: Can't use function '\r' in math mode at position 18: …LENGTH(hkey2),'\̲r̲\n',hkey2,'\r\n…’,LENGTH(hval2),’\r\n’,hval2,’\r\n’,
‘KaTeX parse error: Can't use function '\r' in math mode at position 18: …LENGTH(hkey3),'\̲r̲\n',hkey3,'\r\n…’,LENGTH(hval3),’\r\n’,hval3,’\r’
)FROM(
SELECT ‘HMSET’ AS redis_cmd,
concat_ws(’:’,‘person’, id) AS redis_key,
‘id’ AS hkey1, id AS hval1,
‘name’ AS hkey2, name AS hval2,
‘age’ AS hkey3, age AS hval3
From person
)AS t
Windows下的命令为:
SELECT CONCAT(
“*8\n”,
‘$’,LENGTH(redis_cmd),’\n’,redis_cmd,’\n’,
‘$’,LENGTH(redis_key),’\n’,redis_key,’\n’,
‘KaTeX parse error: Undefined control sequence: \n at position 18: …LENGTH(hkey1),'\̲n̲',hkey1,'\n','’,LENGTH(hval1),’\n’,hval1,’\n’,
‘KaTeX parse error: Undefined control sequence: \n at position 18: …LENGTH(hkey2),'\̲n̲',hkey2,'\n','’,LENGTH(hval2),’\n’,hval2,’\n’,
‘KaTeX parse error: Undefined control sequence: \n at position 18: …LENGTH(hkey3),'\̲n̲',hkey3,'\n','’,LENGTH(hval3),’\n’,hval3
)FROM(
SELECT ‘HMSET’ AS redis_cmd,
concat_ws(’:’,‘person’, id) AS redis_key,
‘id’ AS hkey1, id AS hval1,
‘name’ AS hkey2, name AS hval2,
‘age’ AS hkey3, age AS hval3
From person
)AS t
这个查询语句最后的结果每一行都是如下的一个resp协议格式的命令:
*8\r\n$5\r\nHMSET\r\n$8\r\nperson:1\r\n$2\r\nid\r\n$1\r\n1\r\n$4\r\nname\r\n$5\r\nTommy\r\n$3\r\nage\r\n$2\r\n18
然后将上面的查询语句存储到一个脚本文件比如/usr/local/person.sql
调用sql脚本并执行redis命令
mysql -uroot -ppassword dbname --default-character-set=utf8 --skip-column-names --raw < /usr/local/person.sql | redis-cli --pipe
其中:
-u 是数据库用户名 -p 是数据库密码 -D 指定数据库,也可以直接输入数据库名字
–default-character-set=utf8 使用utf8作为默认编码
–raw 使mysql不转换字段值中的换行符 --skip-column-names 使mysql输出的每行中不包含列名
| 管道符号(意思是将该符号左边的运算结果提交给右边的命令处理)
redis-cli 是调用Redis的客户端命令 --pipe 使用管道传输
执行命令后,如果出现类似以下提示,这说明导入正确:
All data transferred. Waiting for the last reply…
Last reply received from server.
errors: 0, replies: 2
错误处理
ERR Protocol error: expected ‘$’, got ’ ’
如果执行命令时,出现 ERR Protocol error: expected ‘$’, got ’ ’ , 先判断你的操作系统,
如果是在Windows下使用了\r\n作为分隔符就会如此,应改成\n。
ERR Protocol error: expected ‘$’, got ‘1’ 就是got后面的内容不为空 ’ ’
看起来与5.1的错误提示极为相似,但这个一般是数据库中有特殊符号所导致的的,
所以在命令中加上 --default-character-set=utf8 即可