【redis使用系列】redis通信协议及与mysql互通

本文参考资料

https://redis.io/topics/protocol

redis-cli命令与redis通信协议

redis-cli命令

redis命令在从提交到返回处理结果的过程中,消耗的时间我们称之为RTT(往返时间)。在需要批量执行redis 命令的场景下,如果命令单条逐个执行,那么总共花费的时间是命令条数 N * RTT。redis 提供了管道技术来提高批量执行效率,即将多个命令打包发送给redis服务端,所有命令执行完后,再将所有结果打包返回。在所有命令执行结束前,redis服务器会缓存已执行结束的结果。
在redis-cli命令行中,使用redis管道技术时,我们通常将待执行的命令放到一个文本里,比如commands.txt,然后使用命令:

cat commands.txt | redis-cli --pipe

去读取文本里的命令,然后打包已pipe管道的方式发送给redis服务端。
其他命令见

redis通信协议

Redis服务器与客户端通过RESP(REdis Serialization Protocol)协议通信。协议用 \r\n 做间隔。对于简单的字符串,以 + 开头,例如 :+OK\r\n。对于错误消息,以 - 开头 ,例如:

-ERR unknown command 'foobar'\r\n
-WRONGTYPE Operation against a key holding the wrong kind of value\r\n

对于整数,以:开头,例如:

:100\r\n

对于大字符串,以$开头,接着跟上字符串长度的数字。 最长512MB 。 例如:

$6\r\nfoobar\r\n      代表一个长6的字符串, foobar 
$0\r\n\r\n 长度为0 的空字符串
$-1\r\n Null

对于数组, 以 * 开头, 接上数组元素个数。 加数组元素

*0\r\n    一个空的数组
*2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n 一个有两个元素的数组 foo bar

数组可以有更多复杂的用法,具体的建议去看官方文档。此处就不一一介绍了

go与redis通信(2018年补充)

func main() {
tcpAddr, err := net.ResolveTCPAddr("tcp4", "10.2.1.30:6379")
conn, err := net.DialTCP("tcp", nil, tcpAddr)
if err != nil {
fmt.Println(err, conn)
return
}
req := "*3\r\n" +
"$3\r\n" +
"set\r\n" +
"$3\r\n" +
"foo\r\n" +
"$3\r\n" +
"bar\r\n"

conn.Write([]byte(req))

req = "*2\r\n" +
"$3\r\n" +
"get\r\n" +
"$3\r\n" +
"foo\r\n"

buffer := make([]byte, 2048)
conn.Write([]byte(req))
time.Sleep(10 * time.Millisecond)
conn.Read(buffer)
fmt.Println(string(buffer))
}

mysql数据导入redis

mysql数据导入redis

创建表

DROP TABLE IF EXISTS `t_area`;
CREATE TABLE `t_area` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`pid` int(11) NOT NULL,
`areaname` varchar(255) NOT NULL,
`arealevel` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of t_area
-- ----------------------------
INSERT INTO `t_area` VALUES ('1', '0', '北京', '0');
INSERT INTO `t_area` VALUES ('2', '0', '上海', '0');
INSERT INTO `t_area` VALUES ('3', '0', '广州', '0');
INSERT INTO `t_area` VALUES ('4', '0', '深圳', '0');
INSERT INTO `t_area` VALUES ('5', '0', '杭州', '0');

编写脚本

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,
CONCAT('pid:' ,pid) AS redis_key,
id AS hkey,
areaname AS hval
FROM t_area
) AS t;

测试脚本

mysql -uroot -p -h mysql服务器所在ip 数据库名 --skip-column-names --raw < redis.sql

正式执行

mysql -uroot -p -h mysql服务器所在ip 数据库名 --skip-column-names --raw < redis.sql |/usr/local/redis-3.2.12/bin/redis-cli -p 6379 --pipe