当前位置 博文首页 > 韩超的博客 (hanchao5272):Redis: pipeline基本原理以及Jedis和

    韩超的博客 (hanchao5272):Redis: pipeline基本原理以及Jedis和

    作者:[db:作者] 时间:2021-09-05 16:09

    1.关于pipeline

    pipeline即管道的意思,在Redis中,它表示的是一次性执行多条命令

    在原生模式下,

    • 每执行一次redis命令,都需要经过发送命令(I/O)执行命令(内存)返回结果(I/O))三个阶段。

    • 其中,主要耗时在发送命令返回结果

    在pipeline模式下,

    • 一次性执行多条命令,也只需要一次发送命令和一次返回结果
    • 节省了大量花费在I/O上的耗时。

    关于原生模式和pipeline模式可以通过下图直接理解:

    2.性能简单测试

    下面对2000次redis操作进行的耗时测试,分为三种方式:

    • redis的原生模式
    • Jedis包提供的pipeline模式
    • Redisson包提供的

    测试代码:

    /**
     * <p>Redis Pipeline Demo</P>
     *
     * @author hanchao
     */
    @Slf4j
    public class RedisPipelineDemo {
        public static void main(String[] args) {
            //连接redis
            Jedis jedis = new Jedis("127.0.0.1", 6379);
            //获取pipeline
            Pipeline pipeline = jedis.pipelined();
    
            //原生模式
            String zSetKey = "pipeline-test-";
            int size = 1000;
    
            Long begin = System.currentTimeMillis();
            for (int i = 0; i < size; i++) {
                jedis.zadd(zSetKey + i, i, String.valueOf(i));
                jedis.zadd(zSetKey, i + 1, String.valueOf(i + 1));
            }
            log.info("原生模式耗时:{}", (System.currentTimeMillis() - begin));
    
            //pipeline模式
            begin = System.currentTimeMillis();
            for (int i = 0; i < size; i++) {
                pipeline.zadd(zSetKey + i, i, String.valueOf(i));
                pipeline.zadd(zSetKey, i + 1, String.valueOf(i + 1));
            }
            pipeline.sync();
            log.info("pipeline模式(Jedis)耗时:{}", (System.currentTimeMillis() - begin));
    
            //连接redis
            Config config = new Config();
            config.useSingleServer().setAddress("redis://127.0.0.1:6379");
            RedissonClient redisson = Redisson.create(config);
          	//pipeline
            RBatch redisBatch = redisson.createBatch();
    
            begin = System.currentTimeMillis();
            for (int i = 0; i < size; i++) {
                redisBatch.getScoredSortedSet(zSetKey + i).addAsync(i,String.valueOf(i));
                redisBatch.getScoredSortedSet(zSetKey).addAsync(i + 1,String.valueOf(i + 1));
            }
            redisBatch.execute();
            log.info("pipeline模式(Redission)耗时:{}", (System.currentTimeMillis() - begin));
    
            //关闭
            pipeline.close();
            jedis.close();
            redisson.shutdown();
        }
    }
    

    执行结果:

     INFO - 原生模式耗时:6950 
     INFO - pipeline模式(Jedis)耗时:21 
     INFO - pipeline模式(Redission)耗时:197 
    

    可以发现,pipeline模式能够极大的降低耗时。

    3.注意事项

    • 原生模式的每个操作都是原子操作;pipeline模式的操作时非原子性的。
    • 为了保证pipeline的批量操作的原子性,可以通过Redis提供的简单事务控制命令multiexec进行控制。
    • 因为Redis是单线程的,如果单操作耗时太长会阻塞后续请求,所以要控制每次pipeline处理的命令数量,防止执行时间太长。
    cs