Redis pipeline
關於 Redis pipeline
為什麼需要 pipeline ?
Redis 的工作過程是基於 請求/響應 模式的。正常情況下,客戶端發送一個命令,等待 Redis 應答;Redis 接收到命令,處理後應答。請求發出到響應的時間叫做往返時間,即 RTT(Round Time Trip)。在這種情況下,如果需要執行大量的命令,就需要等待上一條命令應答後再執行。這中間不僅僅多了許多次 RTT,而且還頻繁的調用系統 IO,發送網路請求。為了提升效率,pipeline 出現了,它允許客戶端可以一次發送多條命令,而不等待上一條命令執行的結果。
實現思路
客戶端首先將執行的命令寫入到緩衝區中,最後再一次性發送 Redis。但是有一種情況就是,緩衝區的大小是有限制的:如果命令數據太大,可能會有多次發送的過程,但是仍不會處理 Redis 的應答。
實現原理
要支持 pipeline,既要服務端的支持,也要客戶端支持。對於服務端來說,所需要的是能夠處理一個客戶端通過同一個 TCP 連接發來的多個命令。可以理解為,這裡將多個命令切分,和處理單個命令一樣。對於客戶端,則是要將多個命令緩存起來,緩衝區滿了就發送,然後再寫緩衝,最後才處理 Redis 的應答。
Redis pipeline 的參考資料
Redis 官網對於 pipeline 的介紹
Spring Data Redis 對於 pipeline 的介紹
在 SpringBoot 中使用 Redis pipeline
基於 SpringBoot 的自動配置,在使用 Redis 時只需要在 pom 文件中給出 spring-boot-starter-data-redis 依賴,就可以直接使用 Spring Data Redis。關於 Redis pipeline 的使用方法,可以閱讀 Spring Data Redis 給出的解釋。下面,我給出一個簡單的例子:
import com.imooc.ad.Application;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.StringRedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;
/**
*
Redis Pipeline 功能測試用例
* 參考: https://docs.spring.io/spring-data/redis/docs/1.8.1.RELEASE/reference/html/#redis:template
* Created by Qinyi.
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = , webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class RedisPipelineTest {
/** 注入 StringRedisTemplate, 使用默認配置 */
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Test
@SuppressWarnings(all)
public void testExecutePipelined() {
// 使用 RedisCallback 把命令放在 pipeline 中
RedisCallback redisCallback = connection - {
StringRedisConnection stringRedisConn = (StringRedisConnection) connection;
for (int i = 0; i != 10; i) {
stringRedisConn.set(String.valueOf(i), String.valueOf(i));
}
return null; // 這裡必須要返回 null
};
// 使用 SessionCallback 把命令放在 pipeline
SessionCallback sessionCallback = new SessionCallback() {
@Override
public Object execute(RedisOperations operations) throws DataAccessException {
operations.opsForValue().set(name, qinyi);
operations.opsForValue().set(gender, male);
operations.opsForValue().set(age, 19);
return null;
}
};
System.out.println(stringRedisTemplate.executePipelined(redisCallback));
System.out.println(stringRedisTemplate.executePipelined(sessionCallback));
}
}
總結:Redis pipeline 的特性以及使用時需要注意的地方
pipeline 減少了 RTT,也減少了IO調用次數(IO 調用涉及到用戶態到內核態之間的切換)
如果某一次需要執行大量的命令,不能放到一個 pipeline 中執行。數據量過多,網路傳輸延遲會增加,且會消耗 Redis 大量的內存。應該將大量的命令切分為多個 pipeline 分別執行。


※分散式系統中的冪等性-zookeeper與dubbo
※大數據已成為人工智慧的助推力
TAG:千鋒JAVA開發學院 |