zoukankan      html  css  js  c++  java
  • Redis管道之Java与Go代码示例

    最近读了Redis官网一篇关于使用管道加速Redis查询 的文章,原文:Using pipelining to speedup Redis queries,中文翻译可参考:管道(Pipelining)

    一个请求/响应服务器能处理新的请求即使客户端还未读取旧的响应。这样就可以将多个命令发送到服务器,而不用等待回复,最后在一个步骤中读取该答复。

    管道不仅仅是为了减少往返时间(Round Trip Time,简称RTT)引起的延迟成本,它实际上大大提高了给定 Redis 服务器中每秒可执行的操作总量。 这是因为在不使用管道的情况下,从访问数据结构和生成应答的角度来看,为每个命令提供服务非常廉价,但从执行套接字I/O的角度来看,这是非常昂贵的。 这涉及到调用 read() 和 write()系统调用,这意味着从用户区到内核区。 上下文切换是一个巨大的速度损失。

    原文给的代码示例是基于ruby语言,下面我分别展示Java语言和Go语言的Redis管道示例。

    Redis管道Java示例

    语言版本是:

    • JDK:13.0.2
    • Redis客户端:Jedis 3.2.0

    pom.xml(Maven包依赖)

    <dependency>
      <groupId>redis.clients</groupId>
      <artifactId>jedis</artifactId>
      <version>3.2.0</version>
      <type>jar</type>
      <scope>compile</scope>
    </dependency>
    

    JedisPipelineDemo.java

    import com.google.common.base.Stopwatch;
    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.Pipeline;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class JedisPipelineDemo {
    
        Jedis jedis = new Jedis("localhost");
    
        void withoutPipeline() {
            for (int i = 0; i < 10000; i++)
                jedis.ping();
        }
    
        void withPipeline() {
            Pipeline p = jedis.pipelined();
            for (int i = 0; i < 10000; i++)
                p.ping();
            p.sync(); // 获取所有的响应
        }
    
        void serialTask() {
            printTime(() -> withoutPipeline(), "withoutPipeline"); // 346.4 ms
            printTime(() -> withPipeline(), "withPipeline");       // 18.34 ms
        }
    
        // 虽然传入的是Runnable对象,直接调用run方法并没有创建线程,而是使用当前线程同步执行方法。
        void printTime(Runnable task, String taskName) {
            Stopwatch stopwatch = Stopwatch.createStarted();
            task.run();
            System.out.println(taskName + " took: " + stopwatch.stop());
        }
    
        public static void main(String[] args) {
            JedisPipelineDemo demo = new JedisPipelineDemo();
            demo.serialTask();
        }
    }
    

    Redis管道Go示例

    语言版本:

    redis_pipeline.go

    package main
    
    import (
    	"github.com/gomodule/redigo/redis"
    	"log"
    	"time"
    )
    
    var (
    	c     redis.Conn
    	err   error
    	reply interface{}
    )
    
    func init() {
    	c, err = redis.Dial("tcp", "127.0.0.1:6379")
    	if err != nil {
    		log.Fatal(err)
    	}
    }
    
    func main() {
    	defer c.Close()
    	withoutPipelining() // 256.53 ms
    	withPipelining()    // 8.69 ms
    }
    
    func withoutPipelining() {
    	defer timeTrack(time.Now(), "withoutPipelining")
    	for i := 0; i < 10000; i++ {
    		c.Do("PING")
    	}
    }
    
    func withPipelining() {
    	defer timeTrack(time.Now(), "withPipelining")
    	c.Send("MULTI")
    	for i := 0; i < 10000; i++ {
    		c.Send("PING")
    	}
    	c.Do("EXEC")
    }
    
    func timeTrack(start time.Time, name string) {
    	elapsed := time.Since(start)
    	log.Printf("%s took %s", name, elapsed)
    }
    
  • 相关阅读:
    输出1到100内前五个可以被3整除的数 while for
    Java:运用while()与do....while与for()
    break & continue
    while循环
    for循环例子
    if语句条件
    上位机开发二----第一个程序hallo world
    c语言获取数组长度的三种方法
    halcon标定后畸变校正与测量
    海康相机SDK联合c++标定
  • 原文地址:https://www.cnblogs.com/sxpujs/p/12431261.html
Copyright © 2011-2022 走看看