Redis 使用的是客户端 - 服务器 (CS) 模型和请求 / 响应协议的 TCP 服务器. Redis 客户端与 Redis 服务器之间使用 TCP 协议进行连接, 一个客户端可以通过一个 socket 连接发起多个请求命令. 每个请求命令发出后 client 通常会阻塞并等待 Redis 服务器处理, Redis 处理完请求命令后会将结果通过响应报文返回给 client, 因此当执行多条命令的时候都需要等待上一条命令执行完毕才能执行.
然而使用 Pipeline 模式, 客户端可以一次性发送多条命令, 并在执行完后一次性将结果返回. 这样就大大的减少了网络往返时间, 提高了系统性能.
下面用一个例子测试这两种模式在效率上的差别:
Maven 依赖
- <dependency>
- <groupId>Redis.clients</groupId>
- <artifactId>jedis</artifactId>
- <version>2.9.0</version>
- </dependency>
Jedis 工具类
- import Redis.clients.jedis.Jedis;
- import Redis.clients.jedis.JedisPool;
- import Redis.clients.jedis.JedisPoolConfig;
- public class JedisUtil {
- private static JedisPool pool;
- static {
- int redisTimeout = 30000;
- String redisHost = "127.0.0.1";
- int redisPort = 22621;
- String redisPassword = "36a20fded94c4319a1986efbf3046ba3";
- JedisPoolConfig poolConfig = new JedisPoolConfig();
- poolConfig.setMaxTotal(100);
- // 最大空闲连接数
- poolConfig.setMaxIdle(10);
- // 获取 Jedis 连接的最大等待时间(50 秒)
- poolConfig.setMaxWaitMillis(50 * 1000);
- // 在获取 Jedis 连接时, 自动检验连接是否可用
- poolConfig.setTestOnBorrow(true);
- // 在将连接放回池中前, 自动检验连接是否有效
- poolConfig.setTestOnReturn(true);
- // 自动测试池中的空闲连接是否都是可用连接
- poolConfig.setTestWhileIdle(true);
- // 创建连接池
- pool = new JedisPool(poolConfig, redisHost, redisPort, redisTimeout,redisPassword);
- }
- public static Jedis getResource(){
- return pool.getResource();
- }
- public static void close(){
- pool.close();
- }
- }
测试类
- import Redis.clients.jedis.*;
- public class JedisPipelineTest {
- private static int count = 10000;
- public static void main(String[] args){
- useNormal();
- usePipeline();
- }
- public static void usePipeline(){
- Jedis jedis = JedisUtil.getResource();
- Pipeline pipeline = jedis.pipelined();
- long begin = System.currentTimeMillis();
- for(int i = 0;i<count;i++){
- pipeline.setex("pipe_"+i,1000,"value_"+i);
- }
- pipeline.sync();
- jedis.close();
- System.out.println("usePipeline total time:" + (System.currentTimeMillis() - begin));
- }
- public static void useNormal(){
- Jedis jedis = JedisUtil.getResource();
- long begin = System.currentTimeMillis();
- for(int i = 0;i<count;i++){
- jedis.setex("key_"+i,1000,"value_"+i);
- }
- jedis.close();
- System.out.println("useNormal total time:" + (System.currentTimeMillis() - begin));
- }
- }
测试结果
- useNormal total time:30771
- usePipeline total time:62
从测试的结果可以看出, pipeline 在 "批量处理" 时的优势, 使用 pipeline 的效率要远高于普通的访问方式.
需要注意到是用 pipeline 方式打包命令发送, Redis 必须在处理完所有命令前先缓存起所有命令的处理结果. 打包的命令越多, 缓存消耗内存也越多. 所以并不是打包的命令越多越好.
来源: https://www.cnblogs.com/xiaodf/p/10919463.html