12. SDR 管道API-pipleline

1. Redis 的pipeline

1.1 什麼是pipeline

Redis 中的pipeline 管道命令類似於批處理執行命令。 普通執行一次Redis 命令會進行一次TCP連接的創建與銷燬, 執行多條Redis 命令就會進行多次TCP連接的創建與銷燬, 而TCP 連接的創建與銷燬時比較耗時。 採用pipeline技術, 是先將多條命令添加到隊列中,然後創建一次TCP連接,將每次命令的執行結果(返回值爲非void的命令)依次添加到list中,然後一次性返回,最後關閉TCP連接。

1.2 pipeline 特點

  • 一次pipeline 操作只創建和銷燬一次TCP連接
  • pipeline 中的多條命令存儲在一個隊列中,所以命令執行是有順序的
  • pipeline 中每條返回值不是void的命令都會返回一個結果,然後存儲在List中. 縱使返回值爲null
  • pipeline 中返回值爲void的命令, 不會返回結果, 也就是說list中不會有此對象的返回值.
  • pipeline 中允許執行不同的命令

1.3 SDR API

SDR 提供了兩中API來執行pipeline命令,區別在於對命令返回的結果進行反向序列化時,使用redisTemplate自身的valueSerializer,還是使用自定義的valueSerializer. 通常使用第一種方式即可.

API 簽名 方法描述
public List executePipelined(RedisCallback<?> action) 執行pipeline命令,使用redisTemplate的valueSerializer對結果進行解析
public List executePipelined(RedisCallback<?> action, @Nullable RedisSerializer<?> resultSerializer) 執行pipleLine命令, 使用自定義的serializer 對結果集進行解析

2. API 測試

筆者構造四條命令來測試pipeline 的執行機制:

  • 命令一返回爲A, 所以list中添加第一個元素
  • 命令二返回爲void,所以list中不添加
  • 命令三返回爲null, 所以list中添加第二個元素,只不過值爲null
  • 命令四返回爲B,所以list中添加第三個元素

2.1 默認序列化方式執行pipeline

  • 筆者使用stringRedisTemplate 開啓pipeline , 所以pipeline 中value序列化爲stringRedisTemplate的序列化方式, 即StringRedisSerializer.
  • 每個命令返回值都會使用StringRedisSerializer進行反向序列化。
@Test
public void test() {

    // 初始化數據10條數據
    ListOperations<String, String> ops = stringRedisTemplate.opsForList();
    ops.leftPush("queue", "{\"@class\":\"org.zongf.learn.sdr.l01.UserPO\",\"username\":\"zhangsan\",\"password\":\"123456\",\"age\":20}");
    ops.leftPush("queue", "{\"@class\":\"org.zongf.learn.sdr.l01.UserPO\",\"username\":\"zhangsan\",\"password\":\"123456\",\"age\":20}\n");

    // 管道符獲取命令
    List<Object> list = stringRedisTemplate.executePipelined(new RedisCallback<Object>() {
        @Override
        public Object doInRedis(RedisConnection connection) throws DataAccessException {
            // 使用StringRedisTemplate, 可以將RedisConnection 轉換爲StringRedisConnection
            StringRedisConnection stringRedisConnection = (StringRedisConnection) connection;

            // 返回值爲string
            stringRedisConnection.rPop("queue");

            // 返回值爲void
            stringRedisConnection.slaveOfNoOne();

            // 返回值爲null
            stringRedisConnection.rPop("no-exsists-queue");

            // 返回值爲string
            stringRedisConnection.rPop("queue");

            return null;
        }
    });

    for (Object object : list) {
        String clz = object != null ? object.getClass().toString() : null;
        System.out.println(clz + "--> " + object);

    }
}

輸出結果:

class java.lang.String--> {"@class":"org.zongf.learn.sdr.l01.UserPO","username":"zhangsan","password":"123456","age":20}
null--> null
class java.lang.String--> {"@class":"org.zongf.learn.sdr.l01.UserPO","username":"zhangsan","password":"123456","age":20}

2.2 自定義序列化方式

  • 筆者使用json 序列化工具反向解析每個命令的執行結果, 所以返回結果可以直接是List
  • 使用指定Serializer 方式API時, RedisConnection 不能再轉換爲StringRedisConnection
@Test
public void test2() {

    // 初始化數據10條數據
    ListOperations<String, String> ops = stringRedisTemplate.opsForList();
    ops.leftPush("queue", "{\"@class\":\"org.zongf.learn.sdr.l01.UserPO\",\"username\":\"zhangsan\",\"password\":\"123456\",\"age\":20}");
    ops.leftPush("queue", "{\"@class\":\"org.zongf.learn.sdr.l01.UserPO\",\"username\":\"zhangsan\",\"password\":\"123456\",\"age\":20}\n");

    // 管道符獲取命令
    List<UserPO> list = redisTemplate.executePipelined(new RedisCallback<Object>() {
        @Override
        public Object doInRedis(RedisConnection connection) throws DataAccessException {

            // 返回值爲string
            connection.rPop("queue".getBytes());

            // 返回值爲void
            connection.slaveOfNoOne();

            // 返回值爲null
            connection.rPop("no-exsists-queue".getBytes());

            // 返回值爲string
            connection.rPop("queue".getBytes());

            return null;
        }
    }, new GenericJackson2JsonRedisSerializer());

    System.out.println("result:" + list);
}

輸出結果:

class org.zongf.learn.sdr.l01.UserPO--> UserPO{username='zhangsan', password='123456', age=20}
null--> null
class org.zongf.learn.sdr.l01.UserPO--> UserPO{username='zhangsan', password='123456', age=20}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章