redis pipeline批量處理提升性能

Redis使用的是客戶端-服務器(CS)模型和請求/響應協議的TCP服務器。Redis客戶端與Redis服務器之間使用TCP協議進行鏈接,一個客戶端能夠經過一個socket鏈接發起多個請求命令。每一個請求命令發出後client一般會阻塞並等待redis服務器處理,redis處理完請求命令後會將結果經過響應報文返回給client,所以當執行多條命令的時候都須要等待上一條命令執行完畢才能執行。redis

然而使用Pipeline模式,客戶端能夠一次性發送多條命令,並在執行完後一次性將結果返回。這樣就大大的減小了網絡往返時間,提升了系統性能。shell

下面用一個例子測試這兩種模式在效率上的差異:緩存

Maven依賴服務器

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
</dependency>

Jedis工具類網絡

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class JedisUtil {
    private static JedisPool pool;

    static {
        int redisTimeout = 30000;
        String redisHost = "127.0.0.1";
        int redisPort = 22621;
        String redisPassword = "36a20fded94c4319a1986efbf3046ba3";

        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(100);
        //最大空閒鏈接數
        poolConfig.setMaxIdle(10);
        //獲取Jedis鏈接的最大等待時間(50秒)
        poolConfig.setMaxWaitMillis(50 * 1000);
        //在獲取Jedis鏈接時,自動檢驗鏈接是否可用
        poolConfig.setTestOnBorrow(true);
        //在將鏈接放回池中前,自動檢驗鏈接是否有效
        poolConfig.setTestOnReturn(true);
        //自動測試池中的空閒鏈接是否都是可用鏈接
        poolConfig.setTestWhileIdle(true);
        //建立鏈接池
        pool = new JedisPool(poolConfig, redisHost, redisPort, redisTimeout,redisPassword);
    }
    public static Jedis getResource(){
        return pool.getResource();
    }
    public static void close(){
        pool.close();
    }
}

測試類socket

import redis.clients.jedis.*;

public class JedisPipelineTest {
    private static int count = 10000;
    public static void main(String[] args){
        useNormal();
        usePipeline();
    }
    public static void usePipeline(){
        Jedis jedis = JedisUtil.getResource();
        Pipeline pipeline = jedis.pipelined();
        long begin = System.currentTimeMillis();
        for(int i = 0;i<count;i++){
            pipeline.setex("pipe_"+i,1000,"value_"+i);
        }
        pipeline.sync();
        jedis.close();
        System.out.println("usePipeline total time:" + (System.currentTimeMillis() - begin));
    }
    public static void useNormal(){
        Jedis jedis = JedisUtil.getResource();
        long begin = System.currentTimeMillis();
        for(int i = 0;i<count;i++){
            jedis.setex("key_"+i,1000,"value_"+i);
        }
        jedis.close();
        System.out.println("useNormal total time:" + (System.currentTimeMillis() - begin));
    }
}

測試結果工具

useNormal total time:30771
usePipeline total time:62

從測試的結果能夠看出,pipeline在「批量處理」時的優點,使用pipeline的效率要遠高於普通的訪問方式。性能

須要注意到是用 pipeline方式打包命令發送,redis必須在處理完全部命令前先緩存起全部命令的處理結果。打包的命令越多,緩存消耗內存也越多。因此並非打包的命令越多越好。測試

相關文章
相關標籤/搜索