阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

如何高效地向Redis写入大量的数据

93次阅读
没有评论

共计 3569 个字符,预计需要花费 9 分钟才能阅读完成。

最近有个哥们在群里问,有一个日志,里面存的是 IP 地址(一行一个),如何将这些 IP 快速导入到 Redis 中。

我刚开始的建议是 Shell+redis 客户端。

今天,查看 Redis 官档,发现文档的首页部分(http://www.redis.io/documentation)有一个专门的主题是讲述“Redis Mass Insertion”的,才知道自己的建议很 low。

官方给出的理由如下:

Using a normal Redis client to perform mass insertion is not a good idea for a few reasons: the naive approach of sending one command after the other is slow because you have to pay for the round trip time for every command. It is possible to use pipelining, but for mass insertion of many records you need to write new commands while you read replies at the same time to make sure you are inserting as fast as possible.

Only a small percentage of clients support non-blocking I/O, and not all the clients are able to parse the replies in an efficient way in order to maximize throughput. For all this reasons the preferred way to mass import data into Redis is to generate a text file containing the Redis protocol, in raw format, in order to call the commands needed to insert the required data.

大意是:

1> 每个 redis 客户端命令之间有往返时延。

2> 只要一部分客户端支持非阻塞 I /O。

个人理解是,redis 命令从执行到结果返回,有一定的时延,即便采用多个 redis 客户单并发插入,也很难提高吞吐量,因为,只有非阻塞 I / O 只能针对有限个连接操作。

那么如何高效的写入呢?

官方在 2.6 版本推出了一个新的功能 -pipe mode,即将支持 Redis 协议的文本文件直接通过 pipe 导入到服务端。

说来拗口,具体实现步骤如下:

1. 新建一个文本文件,包含 redis 命令

SET Key0 Value0
SET Key1 Value1
...
SET KeyN ValueN

如果有了原始数据,其实构造这个文件并不难,譬如 shell,Python 都可以

2. 将这些命令转化成 Redis Protocol。

因为 Redis 管道功能支持的是 Redis Protocol,而不是直接的 Redis 命令。

如何转化,可参考后面的脚本。

3. 利用管道插入

cat data.txt | redis-cli --pipe

Shell VS Redis pipe

下面通过测试来具体看看 Shell 批量导入和 Redis pipe 之间的效率。

测试思路:分别通过 shell 脚本和 Redis pipe 向数据库中插入 10 万相同数据,查看各自所花费的时间。

Shell

脚本如下:

#!/bin/bash
for ((i=0;i<100000;i++))
do
echo -en "helloworld" | redis-cli -x set name$i >>redis.log
done

每次写入的值都是 helloworld,但键不同,name0,name1…name99999。

Redis pipe

Redis pipe 会稍微麻烦一点

1> 首先构造 redis 命令的文本文件

在这里,我选用了 python

#!/usr/bin/python
for i in range(100000):
    print 'set name'+str(i),'helloworld'

# python 1.py > redis_commands.txt

# head -2 redis_commands.txt 

set name0 helloworld
set name1 helloworld

2> 将这些命令转化成 Redis Protocol

在这里,我利用了 github 上一个 shell 脚本,

#!/bin/bash

while read CMD; do
  # each command begins with *{number arguments in command}\r\n
  XS=($CMD); printf "*${#XS[@]}\r\n"
  # for each argument, we append ${length}\r\n{argument}\r\n
  for X in $CMD; do printf "\$${#X}\r\n$X\r\n"; done
done < redis_commands.txt
 

# sh 20.sh > redis_data.txt

# head -7 redis_data.txt 

*3
$3
set
$5
name0
$10
helloworld

至此,数据构造完毕。

测试结果

如下:

如何高效地向 Redis 写入大量的数据

时间消耗完全不是一个量级的。

最后,来看看 pipe 的实现原理,

  • redis-cli –pipe tries to send data as fast as possible to the server.
  • At the same time it reads data when available, trying to parse it.
  • Once there is no more data to read from stdin, it sends a special ECHO command with a random 20 bytes string: we are sure this is the latest command sent, and we are sure we can match the reply checking if we receive the same 20 bytes as a bulk reply.
  • Once this special final command is sent, the code receiving replies starts to match replies with this 20 bytes. When the matching reply is reached it can exit with success.

即它会尽可能快的将数据发送到 Redis 服务端,并尽可能快的读取并解析数据文件中的内容,一旦数据文件中的内容读取完了,它会发送一个带有 20 个字节的字符串的 echo 命令,Redis 服务端即根据此命令来确认数据已插入完毕。

总结:

后续有童鞋好奇,构造 redis 命令的时间和将命令转化为 protocol 的时间,这里一并贴下:

[root@MySQL-server1 ~]# time python 1.py > redis_commands.txt

real    0m0.110s
user    0m0.070s
sys    0m0.040s
[root@mysql-server1 ~]# time sh 20.sh > redis_data.txt

real    0m7.112s
user    0m5.861s
sys    0m1.255s

下面关于 Redis 的文章您也可能喜欢,不妨参考下:

Ubuntu 14.04 下 Redis 安装及简单测试 http://www.linuxidc.com/Linux/2014-05/101544.htm

Redis 主从复制基本配置 http://www.linuxidc.com/Linux/2015-03/115610.htm

Redis 集群明细文档 http://www.linuxidc.com/Linux/2013-09/90118.htm

Ubuntu 12.10 下安装 Redis(图文详解)+ Jedis 连接 Redis http://www.linuxidc.com/Linux/2013-06/85816.htm

Redis 系列 - 安装部署维护篇 http://www.linuxidc.com/Linux/2012-12/75627.htm

CentOS 6.3 安装 Redis http://www.linuxidc.com/Linux/2012-12/75314.htm

Redis 安装部署学习笔记 http://www.linuxidc.com/Linux/2014-07/104306.htm

Redis 配置文件 redis.conf 详解 http://www.linuxidc.com/Linux/2013-11/92524.htm

Redis 的详细介绍:请点这里
Redis 的下载地址:请点这里

本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-04/130825.htm

正文完
星哥说事-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-22发表,共计3569字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中