• Redis


    一、管道概念

    1.1 为什么要有redis管道?

    redis本身处理速度很快,但是如果你连续调用10条redis命令,它们要有10个网络来回,这速度就会降下来了,那么有没有办法把这10条命令一起发送到服务端呢?有,它就是redis管道

    1.2 redis管道的本质是什么?

    redis管道的本质是将要发往redis服务端执行的命令在客户端缓存起来,比如说缓存100条,然后你可以将这100条命令一起发送到redis服务端,从而将100个网络来回降低到1个来回,大大降低了网络开销,提升了性能。

    1.3 redis管道优点是什么?

    优点:

    • 多个指令之间没有依赖关系,一个命令出问题,不影响其他命令;
    • 可以使用 pipeline 一次性执行多个指令,减少 IO,缩减时间。

    特点:

    • redis的管道,是客户端实现的技术,服务端稍微配合一下即可(读取批量命令执行,每条命令执行完后进行缓存,全部执行完后再一次性返回)。
    • 优点是大大减少了网络请求次数,提高了性能
    • 注意:由于执行结果是批量返回的,所以管道中的命令不宜太多,否则redis服务端的缓存压力将会变大,进而影响性能。
    • 注意:管道中的命令适合彼此没有关联的命令,如果一个命令的执行依赖上次执行的结果,那就不要用管道了。

    二、Redis管道 vs Redis事务

    从下方的流程图,可以看出区别:

    1.命令在哪里缓存:

    • 事务里面的命令是在服务端缓存,当发出exec命令的时候,服务端就会判断并执行事务命令。
    • 管道里面的命令是在客户端缓存,当客户端结束管道后一次发送到服务端,服务端读取后按照先后顺序先后执行。
    • 但不管是事务还是管道,服务端都需要缓存单个命令的执行结果,等全部执行完后再返回给客户端

    2.命令中出现语法错误,是否影响其他命令:

    • 事务里的命令如果有语法错误(比如:getset name,注意不是执行错误),会导致事务被丢弃,里面的命令都不会执行
    • 而管道里的命令如果出现语法错误,依然不影响其他的命令执行

    3.命令执行过程:

    • 事务和管道里的命令执行过程中都不能被其他的命令插入(事务的肯定不会打断,管道的暂时认为不会打断吧)
    • 事务的命令指向前需要判断watch指定的值是否改变,如果改变了就不执行,而管道不会判断

    事务流程图:

    在这里插入图片描述

    管道流程图:
    在这里插入图片描述

    三、代码示例:使用pipeline

    下面就来对比一下使用管道和不使用管道的速度差异。

    public class JedisDemo {
    
        private static int COMMAND_NUM = 1000;
    
        private static String REDIS_HOST = "Redis服务器IP";
    
        public static void main(String[] args) {
    
            Jedis jedis = new Jedis(REDIS_HOST, 6379);
            withoutPipeline(jedis);
            withPipeline(jedis);
        }
    
        private static void withoutPipeline(Jedis jedis) {
            Long start = System.currentTimeMillis();
            for (int i = 0; i < COMMAND_NUM; i++) {
                jedis.set("no_pipe_" + String.valueOf(i), String.valueOf(i), SetParams.setParams().ex(60));
            }
            long end = System.currentTimeMillis();
            long cost = end - start;
            System.out.println("withoutPipeline cost : " + cost + " ms");
        }
    
        private static void withPipeline(Jedis jedis) {
            Pipeline pipe = jedis.pipelined();
            long start_pipe = System.currentTimeMillis();
            for (int i = 0; i < COMMAND_NUM; i++) {
                pipe.set("pipe_" + String.valueOf(i), String.valueOf(i), SetParams.setParams().ex(60));
            }
            pipe.sync(); // 获取所有的response
            long end_pipe = System.currentTimeMillis();
            long cost_pipe = end_pipe - start_pipe;
            System.out.println("withPipeline cost : " + cost_pipe + " ms");
        }
    }

    结果也符合我们的预期:

    withoutPipeline cost : 11791 ms
    withPipeline cost : 55 ms

    参考文献

    版权声明:本文为CSDN博主「jackletter」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/u010476739/article/details/105252038

  • 相关阅读:
    PHP小案例
    PHP函数
    PHP基础语法
    PHP基础知识
    tp5.1前台模板的系统变量输出
    PHP常用方法很有意义的博客网址
    VS 2010(2005)Unicode使用cximage库Load函数问题
    坑爹的CFile::Remove
    固定CDockablePane的一些小技巧
    (转)理解Bitblt、StretchBlt与SetDIBitsToDevice、StretchDibits
  • 原文地址:https://www.cnblogs.com/frankcui/p/15358577.html
Copyright © 2020-2023  润新知