redis 管道

2017年08月07日 14:54 | 2641次浏览 作者原创 版权保护

管道(pipeline)将客户端 client 与服务器端的交互明确划分为单向的发送请求(Send Request)和接收响应(Receive Response):用户可以将多个操作连续发给服务器,但在此期间服务器端并不对每个操作命令发送响应数据;全部请求发送完毕后用户关闭请求,开始接收响应获取每个操作命令的响应结果。

管道(pipeline)在某些场景下非常有用,比如有多个操作命令需要被迅速提交至服务器端,但用户并不依赖每个操作返回的响应结果,对结果响应也无需立即获得,那么管道就可以用来作为优化性能的批处理工具。性能提升的原因主要是减少了 TCP 连接中交互往返的开销。

不过在程序中使用管道请注意,使用 pipeline 时客户端将独占与服务器端的连接,此期间将不能进行其他“非管道”类型操作,直至 pipeline 被关闭;如果要同时执行其他操作,可以为 pipeline 操作单独建立一个连接,将其与常规操作分离开来。

代码示例-性能对比

public class RedisPipelinePerformanceDemo {
    public static void main(String[] args) {
        Jedis jedis = new Jedis(host, port);
        //ApsaraDB for Redis的实例密码
        String authString = jedis.auth(host+":"+password);// password
        if (!authString.equals("OK")) {
            System.err.println("AUTH Failed: " + authString);
            jedis.close();
            return;
        }
        //连续执行多次命令操作
        final int COUNT=5000;
        String key = "KVStore-Tanghan";
        // 1 ---不使用pipeline操作---
        jedis.del(key);//初始化key
        Date ts1 = new Date();
        for (int i = 0; i < COUNT; i++) {
            //发送一个请求,并接收一个响应(Send Request and  Receive Response)
            jedis.incr(key);
        }
        Date ts2 = new Date();
        System.out.println("不用Pipeline > value为:"+jedis.get(key)+" > 操作用时:" + (ts2.getTime() - ts1.getTime())+ "ms");
        //2 ----对比使用pipeline操作---
        jedis.del(key);//初始化key
        Pipeline p1 = jedis.pipelined();
        Date ts3 = new Date();
        for (int i = 0; i < COUNT; i++) {
            //发出请求 Send Request
            p1.incr(key);
        }
        //接收响应 Receive Response
        p1.sync();
        Date ts4 = new Date();
        System.out.println("使用Pipeline > value为:"+jedis.get(key)+" > 操作用时:" + (ts4.getTime() - ts3.getTime())+ "ms");
        jedis.close();
    }
}

运行结果

不用Pipeline > value为:5000 > 操作用时:211707ms

使用Pipeline > value为:5000 > 操作用时:609ms


代码示例-响应数据的两种处理方式

public class PipelineClientDemo {
    public static void main(String[] args) {
        Jedis jedis = new Jedis(host, port);
        // ApsaraDB for Redis的实例密码
        String authString = jedis.auth(host+":"+password);// password
        if (!authString.equals("OK")) {
            System.err.println("AUTH Failed: " + authString);
            jedis.close();
            return;
        }
        String key = "KVStore-Test1";
        jedis.del(key);//初始化

        // -------- 方法1
        Pipeline p1 = jedis.pipelined();
        System.out.println("-----方法1-----");
        for (int i = 0; i < 5; i++) {
            p1.incr(key);
            System.out.println("Pipeline发送请求");
        }
        // 发送请求完成,开始接收响应
        System.out.println("发送请求完成,开始接收响应");
        List<Object> responses = p1.syncAndReturnAll();
        if (responses == null || responses.isEmpty()) {
            jedis.close();
            throw new RuntimeException("Pipeline error: 没有接收到响应");
        }
        for (Object resp : responses) {
            System.out.println("Pipeline接收响应Response: " + resp.toString());
        }
        System.out.println();

        //-------- 方法2
        System.out.println("-----方法2-----");
        jedis.del(key);//初始化
        Pipeline p2 = jedis.pipelined();
        //需要先声明Response
        Response<Long> r1 = p2.incr(key);
        System.out.println("Pipeline发送请求");
        Response<Long> r2 = p2.incr(key);
        System.out.println("Pipeline发送请求");
        Response<Long> r3 = p2.incr(key);
        System.out.println("Pipeline发送请求");
        Response<Long> r4 = p2.incr(key);
        System.out.println("Pipeline发送请求");
        Response<Long> r5 = p2.incr(key);
        System.out.println("Pipeline发送请求");
        try{
            r1.get();  //此时还未开始接收响应,所以此操作会出错
        }catch(Exception e){
            System.out.println(" <<< Pipeline error:还未开始接收响应  >>> ");
        }
        // 发送请求完成,开始接收响应
        System.out.println("发送请求完成,开始接收响应");
        p2.sync();
        System.out.println("Pipeline接收响应Response: " + r1.get());
        System.out.println("Pipeline接收响应Response: " + r2.get());
        System.out.println("Pipeline接收响应Response: " + r3.get());
        System.out.println("Pipeline接收响应Response: " + r4.get());
        System.out.println("Pipeline接收响应Response: " + r5.get());
        jedis.close();
    }
}

运行结果

-----方法1-----
Pipeline发送请求
Pipeline发送请求
Pipeline发送请求
Pipeline发送请求
Pipeline发送请求
发送请求完成,开始接收响应
Pipeline接收响应Response: 1
Pipeline接收响应Response: 2
Pipeline接收响应Response: 3
Pipeline接收响应Response: 4
Pipeline接收响应Response: 5

-----方法2-----
Pipeline发送请求
Pipeline发送请求
Pipeline发送请求
Pipeline发送请求
Pipeline发送请求
 <<< Pipeline error:还未开始接收响应  >>> 
发送请求完成,开始接收响应
Disconnected from the target VM, address: '127.0.0.1:59635', transport: 'socket'
Pipeline接收响应Response: 1
Pipeline接收响应Response: 2
Pipeline接收响应Response: 3
Pipeline接收响应Response: 4
Pipeline接收响应Response: 5



小说《我是全球混乱的源头》
此文章本站原创,地址 https://www.vxzsk.com/1269.html   转载请注明出处!谢谢!

感觉本站内容不错,读后有收获?小额赞助,鼓励网站分享出更好的教程


上一篇:redis 发布订阅实例 下一篇:松弛变量
^