Redis管道技术

一 问题原因
Redis客户端和服务器之间使用的是TCP协议通信,所以无论发送请求还是接收响应必须经过网络传输,在tcp连接过程中,客户端服务端是阻塞的一问一答通信.

例如在

点击进入---->Redis官网命令测试在线网址
我们输入以下命令:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
一个完整的交互流程如下:

  1. 客户端进程调用write()把消息写入到操作系统内核为Socket分配的send buffer中
  2. 操作系统会把send buffer中的内容写入网卡,网卡再通过网关路由把内容发送到服务器端的网卡
  3. 服务端网卡会把接收到的消息写入操作系统为Socket分配的recv buffer
  4. 服务器进程调用read()读取消息然后进行处理
  5. 处理完成后调用write()把返回结果写入到服务器端的send buffer
  6. 服务器操作系统再将send buffer中的内容写入网卡,然后发送到客户端
  7. 客户端操作系统将网卡内容读到recv buffer中
  8. 客户端进程调用read()从recv buffer中读取消息并返回

命令的执行时间 = 客户端调用write并写网卡时间+一次网络开销的时间+服务读网卡并调用read时间++服务器处理数据时间+服务端调用write并写网卡时间+客户端读网卡并调用read时间


二 适用场景
短时间内发送大量对结果互不依赖结果响应也无需立刻获得那么"管道(pipeline)"可以来充当批处理的工具,
管道在redis里的执行流程如图
在这里插入图片描述

这其中除了网络开销,花费时间最长的就是进行系统调用write()和read()了,这一过程需要操作系统由用户态切换到内核态,中间涉及到的上下文切换会浪费很多时间。

使用管道时,多个命令只会进行一次read()和wrtie()系统调用,因此使用管道会提升Redis服务器处理命令的速度,随着管道中命令的增多,服务器每秒处理请求的数量会线性增长,最后会趋近于不使用管道的10倍。
在这里插入图片描述


三 原理
客户端可以一次发送多条命令,这样在TCP连接中减少了"交互往返"的时间,并且服务端同一返回结果


四 管道技术缺点

如果客户端使用管道发送了多条命令,服务器会将多条命令放入一个队列中,这一操作会消耗一定内存,所以管道命令的数量不是越大越好(太大容易爆内存),而是合理的数量


五 代码实现

package com.admin.until;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.params.SetParams;

public class JedisDemo {

    private static int COMMAND_NUM = 1000;

    private static String REDIS_HOST = "127.0.0.1";

    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");
    }
}

在这里插入图片描述


六 总结

  • 使用管道技术可以显著提升Redis处理命令的速度,其原理就是将多条命令打包,只需要一次网络开销,在服务器端和客户端各一次read()和write()系统调用,以此来节约时间。
  • 管道中的命令数量要适当,并不是越多越好。
  • Redis2.6版本以后,脚本在大部分场景中的表现要优于管道。
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值