首页 > 数据库 >redis 管道 批量处理 transmit multiple commands to the Redis server in one transmission

redis 管道 批量处理 transmit multiple commands to the Redis server in one transmission

时间:2024-09-28 15:47:17浏览次数:1  
标签:commands multiple without Redis server client pipelining

Redis pipelining | Docs https://redis.io/docs/latest/develop/use/pipelining/

Redis pipelining

How to optimize round-trip times by batching Redis commands

Redis pipelining is a technique for improving performance by issuing multiple commands at once without waiting for the response to each individual command. Pipelining is supported by most Redis clients. This document describes the problem that pipelining is designed to solve and how pipelining works in Redis.

Request/Response protocols and round-trip time (RTT)

Redis is a TCP server using the client-server model and what is called a Request/Response protocol.

This means that usually a request is accomplished with the following steps:

  • The client sends a query to the server, and reads from the socket, usually in a blocking way, for the server response.
  • The server processes the command and sends the response back to the client.

So for instance a four commands sequence is something like this:

  • Client: INCR X
  • Server: 1
  • Client: INCR X
  • Server: 2
  • Client: INCR X
  • Server: 3
  • Client: INCR X
  • Server: 4

Clients and Servers are connected via a network link. Such a link can be very fast (a loopback interface) or very slow (a connection established over the Internet with many hops between the two hosts). Whatever the network latency is, it takes time for the packets to travel from the client to the server, and back from the server to the client to carry the reply.

This time is called RTT (Round Trip Time). It's easy to see how this can affect performance when a client needs to perform many requests in a row (for instance adding many elements to the same list, or populating a database with many keys). For instance if the RTT time is 250 milliseconds (in the case of a very slow link over the Internet), even if the server is able to process 100k requests per second, we'll be able to process at max four requests per second.

If the interface used is a loopback interface, the RTT is much shorter, typically sub-millisecond, but even this will add up to a lot if you need to perform many writes in a row.

Fortunately there is a way to improve this use case.

Redis Pipelining

A Request/Response server can be implemented so that it is able to process new requests even if the client hasn't already read the old responses. This way it is possible to send multiple commands to the server without waiting for the replies at all, and finally read the replies in a single step.

This is called pipelining, and is a technique widely in use for many decades. For instance many POP3 protocol implementations already support this feature, dramatically speeding up the process of downloading new emails from the server.

Redis has supported pipelining since its early days, so whatever version you are running, you can use pipelining with Redis. This is an example using the raw netcat utility:

$ (printf "PING\r\nPING\r\nPING\r\n"; sleep 1) | nc localhost 6379
+PONG
+PONG
+PONG

This time we don't pay the cost of RTT for every call, but just once for the three commands.

To be explicit, with pipelining the order of operations of our very first example will be the following:

  • Client: INCR X
  • Client: INCR X
  • Client: INCR X
  • Client: INCR X
  • Server: 1
  • Server: 2
  • Server: 3
  • Server: 4

IMPORTANT NOTE: While the client sends commands using pipelining, the server will be forced to queue the replies, using memory. So if you need to send a lot of commands with pipelining, it is better to send them as batches each containing a reasonable number, for instance 10k commands, read the replies, and then send another 10k commands again, and so forth. The speed will be nearly the same, but the additional memory used will be at most the amount needed to queue the replies for these 10k commands.

It's not just a matter of RTT

Pipelining is not just a way to reduce the latency cost associated with the round trip time, it actually greatly improves the number of operations you can perform per second in a given Redis server. This is because without using pipelining, serving each command is very cheap from the point of view of accessing the data structures and producing the reply, but it is very costly from the point of view of doing the socket I/O. This involves calling the read() and write() syscall, that means going from user land to kernel land. The context switch is a huge speed penalty.

When pipelining is used, many commands are usually read with a single read() system call, and multiple replies are delivered with a single write() system call. Consequently, the number of total queries performed per second initially increases almost linearly with longer pipelines, and eventually reaches 10 times the baseline obtained without pipelining, as shown in this figure.

Pipeline size and IOPs

A real world code example

In the following benchmark we'll use the Redis Ruby client, supporting pipelining, to test the speed improvement due to pipelining:

require 'rubygems'
require 'redis'

def bench(descr)
  start = Time.now
  yield
  puts "#{descr} #{Time.now - start} seconds"
end

def without_pipelining
  r = Redis.new
  10_000.times do
    r.ping
  end
end

def with_pipelining
  r = Redis.new
  r.pipelined do |rp|
    10_000.times do
      rp.ping
    end
  end
end

bench('without pipelining') do
  without_pipelining
end
bench('with pipelining') do
  with_pipelining
end

Running the above simple script yields the following figures on my Mac OS X system, running over the loopback interface, where pipelining will provide the smallest improvement as the RTT is already pretty low:

without pipelining 1.185238 seconds
with pipelining 0.250783 seconds

As you can see, using pipelining, we improved the transfer by a factor of five.

Pipelining vs Scripting

Using Redis scripting, available since Redis 2.6, a number of use cases for pipelining can be addressed more efficiently using scripts that perform a lot of the work needed at the server side. A big advantage of scripting is that it is able to both read and write data with minimal latency, making operations like read, compute, write very fast (pipelining can't help in this scenario since the client needs the reply of the read command before it can call the write command).

Sometimes the application may also want to send EVAL or EVALSHA commands in a pipeline. This is entirely possible and Redis explicitly supports it with the SCRIPT LOAD command (it guarantees that EVALSHA can be called without the risk of failing).

Appendix: Why are busy loops slow even on the loopback interface?

Even with all the background covered in this page, you may still wonder why a Redis benchmark like the following (in pseudo code), is slow even when executed in the loopback interface, when the server and the client are running in the same physical machine:

FOR-ONE-SECOND:
    Redis.SET("foo","bar")
END

After all, if both the Redis process and the benchmark are running in the same box, isn't it just copying messages in memory from one place to another without any actual latency or networking involved?

The reason is that processes in a system are not always running, actually it is the kernel scheduler that lets the process run. So, for instance, when the benchmark is allowed to run, it reads the reply from the Redis server (related to the last command executed), and writes a new command. The command is now in the loopback interface buffer, but in order to be read by the server, the kernel should schedule the server process (currently blocked in a system call) to run, and so forth. So in practical terms the loopback interface still involves network-like latency, because of how the kernel scheduler works.

Basically a busy loop benchmark is the silliest thing that can be done when metering performances on a networked server. The wise thing is just avoiding benchmarking in this way.

RATE THIS PAGE  

redis/client.py 

Pipelines provide a way to transmit multiple commands to the Redis server
in one transmission. This is convenient for batch processing, such as
saving all the values in a list to Redis.

All commands executed within a pipeline are wrapped with MULTI and EXEC
calls. This guarantees all commands executed in the pipeline will be
executed atomically.

Any command raising an exception does *not* halt the execution of
subsequent commands in the pipeline. Instead, the exception is caught
and its instance is placed into the response list returned by execute().
Code iterating over the response list should be able to deal with an
instance of an exception as a potential value. In general, these will be
ResponseError exceptions, such as those raised when issuing a command
on a key of a different datatype.

 

 

 

翻译

搜索

复制

标签:commands,multiple,without,Redis,server,client,pipelining
From: https://www.cnblogs.com/papering/p/18438029

相关文章

  • 9--苍穹外卖-SpringBoot项目中Redis的介绍及其使用实例 详解
    目录Redis入门Redis简介Redis服务启动与停止服务启动命令Redis数据类型5种常用数据类型介绍各种数据类型的特点Redis常用命令字符串操作命令哈希操作命令列表操作命令集合操作命令有序集合操作命令通用命令在java中操作RedisRedis的Java客户端SpringDataRe......
  • Redis入门-五大基本数据类型
    启动我的redis(我的redis是在www下面的server下面的redis下面的src里面去执行下面这串指令,如果你的src在其他地方可以换)./redis-server&cd到src下面对redis进行压力测试宝塔用不了(因为没有这个对应的文件)redis-benchmark-hlocalhost-p6379-c100-n100000常用命令......
  • Redis 和 CDN 的应用场景区别及 Redis 大 Key 解析
    在现代互联网架构中,Redis和CDN都是非常重要的技术工具,它们在不同的应用场景中发挥着关键作用。 一、Redis的应用场景 (一)缓存场景 1. 加速数据访问:在Web应用中,Redis常被用来缓存频繁访问的数据,如数据库查询结果、页面片段等。以电商网站为例,热门商品的信息被缓......
  • 在 Go 语言中使用 Redis 实现事务并保证 ACID 属性及理解隔离级别
    目录一、Redis事务的基本概念二、在Go语言中使用Redis实现事务的步骤(一)安装Redis客户端库(二)创建Redis客户端(三)开启事务(四)执行事务命令(五)提交事务三、保证事务的ACID属性(一)原子性(Atomicity)(二)一致性(Consistency)(三)隔离性(Isolation)(四)持久性(Durability)四、......
  • Redis实战篇
    Redis实战篇涵盖内容如下:1、导入黑马点评项目当前模型1.1导入SQL1.2导入后端项目解压到工作台,用idea打开即可注:不要忘了修改application.yaml文件中的mysql、redis地址信息测试启动项目后,在浏览器访问:http://localhost:8081/shop-type/list,如果可以看......
  • 【洛谷】AT_abc178_d [ABC178D] Redistribution 的题解
    【洛谷】AT_abc178_d[ABC178D]Redistribution的题解洛谷传送门AT传送门题解一个水水的动态规划,阿巴巴巴。题目大概是这样:给定一个正整数SSS,问有多少个数满足以......
  • Redis
    1.名词解释惰性删除:redis中设置了缓存过期时间,通过算法进行随机删除键值,如果某些键值过期后没有被删除,但是遇到查询请求,则会立即删除的这种方式叫做惰性删除(这种方式是被动式触发的,不查询就不会发生。)缓存穿透:查询的数据不存在时,请求会直接请求数据库,不会通过redis的缓存,此现象......
  • redis集群增加减少节点
    redis集群故障切换方案步骤:1、增加临时节点并加入集群2、将故障节点槽位移动到新节点3、剔除故障节点4、备份故障节点配置下架更换5、更换后按照1-3步骤将临时节点剔除,将原故障节点重新加入集群#测试环境为3主3从,有5个keyredis-cli-c-p8102-h172.17.0.89-a123456d......
  • Redis常见面试题
    过期删除策略删除达到过期时间的key。1)定时删除对于每一个设置了过期时间的key都会创建一个定时器,一旦到达过期时间就立即删除。该策略可以立即清除过期的数据,对内存较友好,但是缺点是占用了大量的CPU资源去处理过期的数据,会影响Redis的吞吐量和响应时间。2)惰性删除当......
  • redis有序集合多字段排序
    首先,redis有序集合本身是不支持多字段排序的例如ZADDusers25AliceZADDusers25BobZADDusers10Carol只能通过前面的分数这一个维度来实现,如果现在引入了另一个字段,可以在分数值(利用阿拉伯数字)上做手脚例如,时间维度2023-01-012023-01-022023-01-03这......