Redis 大量数据插入

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介:

有些时候,Redis实例需要装载大量用户在短时间内产生的数据,数以百万计的keys需要被快速的创建。

我们称之为大量数据插入(mass insertion),本文档的目标就是提供如下信息:Redis如何尽可能快的处理数据。

使用Luke协议

使用正常模式的Redis 客户端执行大量数据插入不是一个好主意:因为一个个的插入会有大量的时间浪费在每一个命令往返时间上。使用管道(pipelining)是一种可行的办法,但是在大量插入数据的同时又需要执行其他新命令时,这时读取数据的同时需要确保请可能快的的写入数据。

只有一小部分的客户端支持非阻塞输入/输出(non-blocking I/O),并且并不是所有客户端能以最大限度的提高吞吐量的高效的方式来分析答复。

例如,如果我们需要生成一个10亿的`keyN -> ValueN’的大数据集,我们会创建一个如下的redis命令集的文件:

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

一旦创建了这个文件,其余的就是让Redis尽可能快的执行。在以前我们会用如下的netcat命令执行:

(cat data.txt; sleep 10) | nc localhost 6379 > /dev/null

然而这并不是一个非常可靠的方式,因为用netcat进行大规模插入时不能检查错误。从Redis 2.6开始redis-cli支持一种新的被称之为pipe mode的新模式用于执行大量数据插入工作。

使用pipe mode模式的执行命令如下:

cat data.txt | redis-cli --pipe

这将产生类似如下的输出:

All data transferred. Waiting for the last reply...
Last reply received from server.
errors: 0, replies: 1000000

使用redis-cli将有效的确保错误输出到Redis实例的标准输出里面。

生成Redis协议

它会非常简单的生成和解析Redis协议,Redis协议文档请参考Redis协议说明。 但是为了生成大量数据插入的目标,你需要了解每一个细节协议,每个命令会用如下方式表示:

*<args><cr><lf>
$<len><cr><lf>
<arg0><cr><lf>
<arg1><cr><lf>
...
<argN><cr><lf>

这里的<cr>是”\r”(或者是ASCII的13)、<lf>是”\n”(或者是ASCII的10)。

例如:命令SET key value协议格式如下:

*3<cr><lf>
$3<cr><lf>
SET<cr><lf>
$3<cr><lf>
key<cr><lf>
$5<cr><lf>
value<cr><lf>

或表示为引用字符串:

"*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n"

你需要将大量插入数据的命令按照上面的方式一个接一个的生成到文件。

下面是使用Ruby生成协议的参考:

def gen_redis_proto(*cmd)
    proto = ""
    proto << "*"+cmd.length.to_s+"\r\n"
    cmd.each{|arg|
        proto << "$"+arg.to_s.bytesize.to_s+"\r\n"
        proto << arg.to_s+"\r\n"
    }
    proto
end

puts gen_redis_proto("SET","mykey","Hello World!").inspect

针对上面的例子,使用下面代码可以很容易的生成需要的文件:

(0...1000).each{|n|
    STDOUT.write(gen_redis_proto("SET","Key#{n}","Value#{n}"))
}

我们可以直接用 redis-cli 的 pipe执行我们的第一个大量数据插入命令,过程如下:

$ ruby proto.rb | redis-cli --pipe
All data transferred. Waiting for the last reply...
Last reply received from server.
errors: 0, replies: 1000

pipe mode的工作原理是什么?

难点是保证redis-cli在pipe mode模式下执行和netcat一样快的同时,如何能理解服务器发送的最后一个回复。

这是通过以下方式获得:

  • redis-cli –pipe试着尽可能快的发送数据到服务器。
  • 读取数据的同时,解析它。
  • 一旦没有更多的数据输入,它就会发送一个特殊的ECHO命令,后面跟着20个随机的字符。我们相信可以通过匹配回复相同的20个字符是同一个命令的行为。
  • 一旦这个特殊命令发出,收到的答复就开始匹配这20个字符,当匹配时,就可以成功退出了。

同时,在分析回复的时候,我们会采用计数器的方法计数,以便在最后能够告诉我们大量插入数据的数据量。






本文作者:陈群
本文来自云栖社区合作伙伴rediscn,了解相关信息可以关注redis.cn网站。
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
9天前
|
缓存 NoSQL 关系型数据库
13- Redis和Mysql如何保证数据⼀致?
该内容讨论了保证Redis和MySQL数据一致性的几种策略。首先提到的两种方法存在不一致风险:先更新MySQL再更新Redis,或先删Redis再更新MySQL。第三种方案是通过MQ异步同步以达到最终一致性,适用于一致性要求较高的场景。项目中根据不同业务需求选择不同方案,如对一致性要求不高的情况不做处理,时效性数据设置过期时间,高一致性需求则使用MQ确保同步,最严格的情况可能涉及分布式事务(如Seata的TCC模式)。
35 6
|
9天前
|
NoSQL Redis
05- Redis的数据淘汰策略有哪些 ?
Redis 提供了 8 种数据淘汰策略:挥发性 LRU、LFU 和 TTL(针对有过期时间的数据),挥发性随机淘汰,以及全库的 LRU、LFU 随机淘汰,用于在内存不足时选择删除。另外,还有不淘汰策略(no-eviction),允许新写入操作报错而非删除数据。
11 1
|
16天前
|
NoSQL Redis
Redis事务:保证数据操作的一致性和可靠性
Redis事务:保证数据操作的一致性和可靠性
|
11天前
|
存储 NoSQL 算法
redis数据持久化
redis数据持久化
|
16天前
|
NoSQL 安全 网络安全
保护Redis:建立铁壁般的安全防线,守护你的数据财富
保护Redis:建立铁壁般的安全防线,守护你的数据财富
|
16天前
|
消息中间件 存储 NoSQL
Redis Stream: 实时消息处理的利器,让你的数据流畅又可靠!
Redis Stream: 实时消息处理的利器,让你的数据流畅又可靠!
|
16天前
|
NoSQL 安全 网络安全
Redis连接:加速数据访问与保障安全传输的关键
Redis连接:加速数据访问与保障安全传输的关键
|
16天前
|
存储 消息中间件 缓存
Redis 字符串:用一串数据解决多种问题
Redis 字符串:用一串数据解决多种问题
|
1月前
|
存储 JSON NoSQL
Redis与Python的完美结合:实现高效数据交互和应用场景全解析
Redis与Python的完美结合:实现高效数据交互和应用场景全解析
113 0
|
1月前
|
缓存 NoSQL Java
【九】springboot整合redis实现启动服务时热点数据保存在全局和缓存
【九】springboot整合redis实现启动服务时热点数据保存在全局和缓存
40 0

热门文章

最新文章