533
魔獸
管道傳輸__最佳實踐_雲數據庫 Redis 版-阿裏雲
管道傳輸(pipeline)
場景介紹
ApsaraDB for Redis 提供了與 Redis 相同的管道傳輸(pipeline)機製。管道(pipeline)將客戶端 client 與服務器端的交互明確劃分為單向的發送請求(Send Request)和接收響應(Receive Response):用戶可以將多個操作連續發給服務器,但在此期間服務器端並不對每個操作命令發送響應數據;全部請求發送完畢後用戶關閉請求,開始接收響應獲取每個操作命令的響應結果。
管道(pipeline)在某些場景下非常有用,比如有多個操作命令需要被迅速提交至服務器端,但用戶並不依賴每個操作返回的響應結果,對結果響應也無需立即獲得,那麼管道就可以用來作為優化性能的批處理工具。性能提升的原因主要是減少了 TCP 連接中交互往返的開銷。
不過在程序中使用管道請注意,使用 pipeline 時客戶端將獨占與服務器端的連接,此期間將不能進行其他“非管道”類型操作,直至 pipeline 被關閉;如果要同時執行其他操作,可以為 pipeline 操作單獨建立一個連接,將其與常規操作分離開來。
代碼示例1
性能對比
package pipeline.kvstore.aliyun.com;
import java.util.Date;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;
public class RedisPipelinePerformanceTest {
static final String host = "xxxxxx.m.cnhza.kvstore.aliyuncs.com";
static final int port = 6379;
static final String password = "password";
public static void main(String[] args) {
Jedis jedis = new Jedis(host, port);
//ApsaraDB for Redis的實例ID及密碼
String authString = jedis.auth(password);// password
if (!authString.equals("OK")) {
System.err.println("AUTH Failed: " + authString);
jedis.close();
return;
}
//連續執行多次命令操作
final int COUNT=5000;
String key = "KVStore-Tanghan";
// 1 ---不使用pipeline操作---
jedis.del(key);//初始化key
Date ts1 = new Date();
for (int i = 0; i < COUNT; i++) {
//發送一個請求,並接收一個響應(Send Request and Receive Response)
jedis.incr(key);
}
Date ts2 = new Date();
System.out.println("不用Pipeline > value為:"+jedis.get(key)+" > 操作用時:" + (ts2.getTime() - ts1.getTime())+ "ms");
//2 ----對比使用pipeline操作---
jedis.del(key);//初始化key
Pipeline p1 = jedis.pipelined();
Date ts3 = new Date();
for (int i = 0; i < COUNT; i++) {
//發出請求 Send Request
p1.incr(key);
}
//接收響應 Receive Response
p1.sync();
Date ts4 = new Date();
System.out.println("使用Pipeline > value為:"+jedis.get(key)+" > 操作用時:" + (ts4.getTime() - ts3.getTime())+ "ms");
jedis.close();
}
}
運行結果1
在輸入了正確的 ApsaraDB for Redis 實例訪問地址和密碼之後,運行以上 Java 程序,輸出結果如下。從中可以看出使用 pipeline 的性能要快的多。
不用Pipeline > value為:5000 > 操作用時:5844ms
使用Pipeline > value為:5000 > 操作用時:78ms
代碼示例2
在 Jedis 中使用管道(pipeline)時,對於響應數據(response)的處理有兩種方式,請參考以下代碼示例。
package pipeline.kvstore.aliyun.com;
import java.util.List;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.Response;
public class PipelineClientTest {
static final String host = "xxxxxxxx.m.cnhza.kvstore.aliyuncs.com";
static final int port = 6379;
static final String password = "password";
public static void main(String[] args) {
Jedis jedis = new Jedis(host, port);
// ApsaraDB for Redis的實例ID及密碼
String authString = jedis.auth(password);// password
if (!authString.equals("OK")) {
System.err.println("AUTH Failed: " + authString);
jedis.close();
return;
}
String key = "KVStore-Test1";
jedis.del(key);//初始化
// -------- 方法1
Pipeline p1 = jedis.pipelined();
System.out.println("-----方法1-----");
for (int i = 0; i < 5; i++) {
p1.incr(key);
System.out.println("Pipeline發送請求");
}
// 發送請求完成,開始接收響應
System.out.println("發送請求完成,開始接收響應");
List<Object> responses = p1.syncAndReturnAll();
if (responses == null || responses.isEmpty()) {
jedis.close();
throw new RuntimeException("Pipeline error: 沒有接收到響應");
}
for (Object resp : responses) {
System.out.println("Pipeline接收響應Response: " + resp.toString());
}
System.out.println();
//-------- 方法2
System.out.println("-----方法2-----");
jedis.del(key);//初始化
Pipeline p2 = jedis.pipelined();
//需要先聲明Response
Response<Long> r1 = p2.incr(key);
System.out.println("Pipeline發送請求");
Response<Long> r2 = p2.incr(key);
System.out.println("Pipeline發送請求");
Response<Long> r3 = p2.incr(key);
System.out.println("Pipeline發送請求");
Response<Long> r4 = p2.incr(key);
System.out.println("Pipeline發送請求");
Response<Long> r5 = p2.incr(key);
System.out.println("Pipeline發送請求");
try{
r1.get(); //此時還未開始接收響應,所以此操作會出錯
}catch(Exception e){
System.out.println(" <<< Pipeline error:還未開始接收響應 >>> ");
}
// 發送請求完成,開始接收響應
System.out.println("發送請求完成,開始接收響應");
p2.sync();
System.out.println("Pipeline接收響應Response: " + r1.get());
System.out.println("Pipeline接收響應Response: " + r2.get());
System.out.println("Pipeline接收響應Response: " + r3.get());
System.out.println("Pipeline接收響應Response: " + r4.get());
System.out.println("Pipeline接收響應Response: " + r5.get());
jedis.close();
}
}
運行結果2
在輸入了正確的 ApsaraDB for Redis 實例訪問地址和密碼之後,運行以上 Java 程序,輸出結果如下:
-----方法1-----
Pipeline發送請求
Pipeline發送請求
Pipeline發送請求
Pipeline發送請求
Pipeline發送請求
發送請求完成,開始接收響應
Pipeline接收響應Response: 1
Pipeline接收響應Response: 2
Pipeline接收響應Response: 3
Pipeline接收響應Response: 4
Pipeline接收響應Response: 5
-----方法2-----
Pipeline發送請求
Pipeline發送請求
Pipeline發送請求
Pipeline發送請求
Pipeline發送請求
<<< Pipeline error:還未開始接收響應 >>>
發送請求完成,開始接收響應
Pipeline接收響應Response: 1
Pipeline接收響應Response: 2
Pipeline接收響應Response: 3
Pipeline接收響應Response: 4
Pipeline接收響應Response: 5
最後更新:2016-12-16 17:25:21
上一篇:
消息發布與訂閱__最佳實踐_雲數據庫 Redis 版-阿裏雲
下一篇:
事務處理__最佳實踐_雲數據庫 Redis 版-阿裏雲
停止實例__實例相關接口_API 參考_雲服務器 ECS-阿裏雲
導出數據庫__導出數據_數據管理_用戶指南(RDBMS)_數據管理-阿裏雲
刪除磁盤__磁盤相關接口_API 參考_雲服務器 ECS-阿裏雲
錯誤日誌__應用操作接口_API參考手冊_開放搜索-阿裏雲
計量計費說明__計量計費_大數據計算服務-阿裏雲
解析線路枚舉__枚舉類型_API文檔_雲解析-阿裏雲
資源申請__MQTT 接入準備_MQTT 接入(物聯)_消息隊列 MQ-阿裏雲
Google Authenticator安裝及使用指導__附錄2: _用戶指南_訪問控製-阿裏雲
ALIYUN::ECS::InstanceGroupClone__資源列表_資源編排-阿裏雲
快速指引__DataHub實時數據通道_大數據計算服務-阿裏雲
相關內容
常見錯誤說明__附錄_大數據計算服務-阿裏雲
發送短信接口__API使用手冊_短信服務-阿裏雲
接口文檔__Android_安全組件教程_移動安全-阿裏雲
運營商錯誤碼(聯通)__常見問題_短信服務-阿裏雲
設置短信模板__使用手冊_短信服務-阿裏雲
OSS 權限問題及排查__常見錯誤及排除_最佳實踐_對象存儲 OSS-阿裏雲
消息通知__操作指南_批量計算-阿裏雲
設備端快速接入(MQTT)__快速開始_阿裏雲物聯網套件-阿裏雲
查詢API調用流量數據__API管理相關接口_API_API 網關-阿裏雲
使用STS訪問__JavaScript-SDK_SDK 參考_對象存儲 OSS-阿裏雲