Redis中的批量操作Pipeline
阿新 • • 發佈:2018-12-10
大多數情況下,我們都會通過請求-相應機制去操作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最好了。