1. 程式人生 > >Redis中的批量操作Pipeline

Redis中的批量操作Pipeline

大多數情況下,我們都會通過請求-相應機制去操作redis。只用這種模式的一般的步驟是,先獲得jedis例項,然後通過jedis的get/put方法與redis互動。由於redis是單執行緒的,下一次請求必須等待上一次請求執行完成後才能繼續執行。然而使用Pipeline模式,客戶端可以一次性的傳送多個命令,無需等待服務端返回。這樣就大大的減少了網路往返時間,提高了系統性能。

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

public class PiplineTest {
    private static int count = 10000;
 
    public static void main(String[] args){
        useNormal();
        usePipeline();
    }
 
    public static void usePipeline(){
        ShardedJedis jedis = getShardedJedis();
        ShardedJedisPipeline pipeline = jedis.pipelined();
        long begin = System.currentTimeMillis();
        for(int i = 0;i<count;i++){
            pipeline.set("key_"+i,"value_"+i);
        }
        pipeline.sync();
        jedis.close();
        System.out.println("usePipeline total time:" + (System.currentTimeMillis() - begin));
    }
 
    public static void useNormal(){
        ShardedJedis jedis = getShardedJedis();
        long begin = System.currentTimeMillis();
        for(int i = 0;i<count;i++){
            jedis.set("key_"+i,"value_"+i);
        }
        jedis.close();
        System.out.println("useNormal total time:" + (System.currentTimeMillis() - begin));
    }
 
    public static ShardedJedis getShardedJedis(){
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(2);
        poolConfig.setMaxIdle(1);
        poolConfig.setMaxWaitMillis(2000);
        poolConfig.setTestOnBorrow(false);
        poolConfig.setTestOnReturn(false);
        JedisShardInfo info1 = new JedisShardInfo("127.0.0.1",6379);
        JedisShardInfo info2 = new JedisShardInfo("127.0.0.1",6379);
        ShardedJedisPool pool = new ShardedJedisPool(poolConfig, Arrays.asList(info1,info2));
        return pool.getResource();
    }
}

輸出結果:

useNormal total time:772
usePipeline total time:112

從測試的結果可以看出,使用pipeline的效率要遠高於普通的訪問方式。

 那麼問題來了,在什麼樣的情景下適合使用pipeline呢?

 有些系統可能對可靠性要求很高,每次操作都需要立馬知道這次操作是否成功,是否資料已經寫進redis了,那這種場景就不適合。

還有的系統,可能是批量的將資料寫入redis,允許一定比例的寫入失敗,那麼這種場景就可以使用了,比如10000條一下進入redis,可能失敗了2條無所謂,後期有補償機制就行了,比如簡訊群發這種場景,如果一下群發10000條,按照第一種模式去實現,那這個請求過來,要很久才能給客戶端響應,這個延遲就太長了,如果客戶端請求設定了超時時間5秒,那肯定就丟擲異常了,而且本身群發簡訊要求實時性也沒那麼高,這時候用pipeline最好了。