等待 Redis 应答

https://zhuanlan.zhihu.com/p/58608323html

 

mq消息合并:因为mq请求发出到响应的时间,即往返时间, RTT(Round Time Trip),每次提交都要消耗RTT,不支持相似redis的pipeline机制。

 

Redis pipeline

关于 Redis pipeline

为何须要 pipeline ?

Redis 的工做过程是基于 请求/响应 模式的。正常状况下,客户端发送一个命令,等待 Redis 应答;Redis 接收到命令,处理后应答。请求发出到响应的时间叫作往返时间,即 RTT(Round Time Trip)。在这种状况下,若是须要执行大量的命令,就须要等待上一条命令应答后再执行。这中间不单单多了许屡次 RTT,并且还频繁的调用系统 IO,发送网络请求。为了提高效率,pipeline 出现了,它容许客户端能够一次发送多条命令,而不等待上一条命令执行的结果。java

实现思路

客户端首先将执行的命令写入到缓冲区中,最后再一次性发送 Redis。可是有一种状况就是,缓冲区的大小是有限制的:若是命令数据太大,可能会有屡次发送的过程,可是仍不会处理 Redis 的应答。web

实现原理

要支持 pipeline,既要服务端的支持,也要客户端支持。对于服务端来讲,所须要的是可以处理一个客户端经过同一个 TCP 链接发来的多个命令。能够理解为,这里将多个命令切分,和处理单个命令同样。对于客户端,则是要将多个命令缓存起来,缓冲区满了就发送,而后再写缓冲,最后才处理 Redis 的应答。redis

Redis pipeline 的参考资料

在 SpringBoot 中使用 Redis pipeline

基于 SpringBoot 的自动配置,在使用 Redis 时只须要在 pom 文件中给出 spring-boot-starter-data-redis 依赖,就能够直接使用 Spring Data Redis。关于 Redis pipeline 的使用方法,能够阅读 Spring Data Redis 给出的解释。下面,我给出一个简单的例子:spring

import com.imooc.ad.Application; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.dao.DataAccessException; import org.springframework.data.redis.connection.StringRedisConnection; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.RedisOperations; import org.springframework.data.redis.core.SessionCallback; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.test.context.junit4.SpringRunner; /**  * <h1>Redis Pipeline 功能测试用例</h1>  * 参考: https://docs.spring.io/spring-data/redis/docs/1.8.1.RELEASE/reference/html/#redis:template  * Created by Qinyi.  */ @RunWith(SpringRunner.class) @SpringBootTest(classes = {Application.class}, webEnvironment = SpringBootTest.WebEnvironment.NONE) public class RedisPipelineTest { /** 注入 StringRedisTemplate, 使用默认配置 */ @Autowired private StringRedisTemplate stringRedisTemplate; @Test @SuppressWarnings("all") public void testExecutePipelined() { // 使用 RedisCallback 把命令放在 pipeline 中  RedisCallback<Object> redisCallback = connection -> { StringRedisConnection stringRedisConn = (StringRedisConnection) connection; for (int i = 0; i != 10; ++i) { stringRedisConn.set(String.valueOf(i), String.valueOf(i)); } return null; // 这里必需要返回 null  }; // 使用 SessionCallback 把命令放在 pipeline  SessionCallback<Object> sessionCallback = new SessionCallback<Object>() { @Override public Object execute(RedisOperations operations) throws DataAccessException { operations.opsForValue().set("name", "qinyi"); operations.opsForValue().set("gender", "male"); operations.opsForValue().set("age", "19"); return null; } }; System.out.println(stringRedisTemplate.executePipelined(redisCallback)); System.out.println(stringRedisTemplate.executePipelined(sessionCallback)); } }

总结:Redis pipeline 的特性以及使用时须要注意的地方

  • pipeline 减小了 RTT,也减小了IO调用次数(IO 调用涉及到用户态到内核态之间的切换)
  • 若是某一次须要执行大量的命令,不能放到一个 pipeline 中执行。数据量过多,网络传输延迟会增长,且会消耗 Redis 大量的内存。应该将大量的命令切分为多个 pipeline 分别执行。
发布于 2019-03-07
相关文章
相关标签/搜索