七的博客

Redisson2.0源码分析2-Redis命令封装

源码分析

Redisson2.0源码分析2-Redis命令封装

命令封装这块的代码并不是特别多。

1. Redis命令细节封装 RedisCommand

这个类封装一个 Redis 命令的所有必要信息,有 Redis 命令名称、Redis命令的参数类型、命令请求以及应答解码器和转换器等。

这个适用于 Redisson 用来描述以及处理 Redis 命令的。对于 Redisson 来说,发送命令编解码以及命令应答处理都应该是一个固定的流程,那么这个流程需要的参数定义就可以写在这个类中。

package org.redisson.client.protocol;

import java.util.Arrays;
import java.util.List;

import org.redisson.client.protocol.convertor.Convertor;
import org.redisson.client.protocol.convertor.EmptyConvertor;
import org.redisson.client.protocol.decoder.MultiDecoder;

public class RedisCommand<R> {

    // Redis 命令参数以及返回值的类型枚举
    public enum ValueType {OBJECT, OBJECTS, MAP_VALUE, MAP_KEY, MAP}

    private ValueType outParamType = ValueType.OBJECT;  // 输出参数的类型,默认为 OBJECT
    private List<ValueType> inParamType = Arrays.asList(ValueType.OBJECT); // 输入参数的类型,默认为 OBJECT
    private final int inParamIndex; // 输入参数的下标

    private final String name;  // 命令的名称
    private final String subName; // 子命令名称

    	
    // 多条 Redis 响应解码器,比如像  Multi 命令这种返回的结果
    private MultiDecoder<R> replayMultiDecoder;  
    // 单条 Redis 回复的解码器
    private Decoder<R> replayDecoder; 
     // 值转换器。比如 Redis 返回 01 ,程序中转成 true false
    Convertor<R> convertor = new EmptyConvertor<R>();

   
    public RedisCommand(RedisCommand<R> command, String name) {
        this.outParamType = command.outParamType;
        this.inParamType = command.inParamType;
        this.inParamIndex = command.inParamIndex;
        this.name = name;
        this.subName = command.subName;
        this.replayMultiDecoder = command.replayMultiDecoder;
        this.replayDecoder = command.replayDecoder;
        this.convertor = command.convertor;
    }

    // 下面一堆重载函数都是为了创建不同的命令对象。
    public RedisCommand(String name) {
        this(name, (String)null);
    }

    public RedisCommand(String name, ValueType outParamType) {
        this(name, (String)null);
        this.outParamType = outParamType;
    }

    public RedisCommand(String name, int objectParamIndex, ValueType inParamType) {
        this(name, null, null, null, objectParamIndex);
        this.inParamType = Arrays.asList(inParamType);
    }

    public RedisCommand(String name, ValueType inParamType, ValueType outParamType) {
        this(name, (String)null);
        this.inParamType = Arrays.asList(inParamType);
        this.outParamType = outParamType;
    }

    public RedisCommand(String name, String subName) {
        this(name, subName, null, null, -1);
    }

    public RedisCommand(String name, String subName, Convertor<R> convertor) {
        this(name, subName, null, null, -1);
        this.convertor = convertor;
    }

    public RedisCommand(String name, String subName, int objectParamIndex) {
        this(name, subName, null, null, objectParamIndex);
    }

    public RedisCommand(String name, int encodeParamIndex) {
        this(name, null, null, null, encodeParamIndex);
    }

    public RedisCommand(String name, int encodeParamIndex, ValueType inParamType, ValueType outParamType) {
        this(name, null, null, null, encodeParamIndex);
        this.inParamType = Arrays.asList(inParamType);
        this.outParamType = outParamType;
    }

    public RedisCommand(String name, int encodeParamIndex, List<ValueType> inParamType, ValueType outParamType) {
        this(name, null, null, null, encodeParamIndex);
        this.inParamType = inParamType;
        this.outParamType = outParamType;
    }

    public RedisCommand(String name, Decoder<R> reponseDecoder, int encodeParamIndex, List<ValueType> inParamType, ValueType outParamType) {
        this(name, null, null, reponseDecoder, encodeParamIndex);
        this.inParamType = inParamType;
        this.outParamType = outParamType;
    }

    public RedisCommand(String name, Decoder<R> reponseDecoder, int encodeParamIndex, List<ValueType> inParamType) {
        this(name, null, null, reponseDecoder, encodeParamIndex);
        this.inParamType = inParamType;
    }

    public RedisCommand(String name, Convertor<R> convertor, int encodeParamIndex, ValueType inParamType) {
        this(name, null, null, null, encodeParamIndex);
        this.convertor = convertor;
        this.inParamType = Arrays.asList(inParamType);
    }

    public RedisCommand(String name, Convertor<R> convertor, int encodeParamIndex, List<ValueType> inParamTypes) {
        this(name, null, null, null, encodeParamIndex);
        this.convertor = convertor;
        this.inParamType = inParamTypes;
    }

    public RedisCommand(String name, Convertor<R> convertor) {
        this(name, convertor, -1);
    }

    public RedisCommand(String name, Convertor<R> convertor, int encodeParamIndex) {
        this(name, null, null, null, encodeParamIndex);
        this.convertor = convertor;
    }

    public RedisCommand(String name, Decoder<R> reponseDecoder) {
        this(name, null, null, reponseDecoder, -1);
    }

    public RedisCommand(String name, Decoder<R> reponseDecoder, int objectParamIndex, ValueType inParamType) {
        this(name, null, null, reponseDecoder, objectParamIndex);
        this.inParamType = Arrays.asList(inParamType);
    }

    public RedisCommand(String name, Decoder<R> reponseDecoder, int objectParamIndex) {
        this(name, null, null, reponseDecoder, objectParamIndex);
    }

    public RedisCommand(String name, MultiDecoder<R> replayMultiDecoder, ValueType outParamType) {
        this(name, replayMultiDecoder, -1);
        this.outParamType = outParamType;
    }

    public RedisCommand(String name, MultiDecoder<R> replayMultiDecoder, int objectParamIndex, ValueType inParamType, ValueType outParamType) {
        this(name, replayMultiDecoder, objectParamIndex);
        this.outParamType = outParamType;
        this.inParamType = Arrays.asList(inParamType);
    }

    public RedisCommand(String name, MultiDecoder<R> replayMultiDecoder) {
        this(name, replayMultiDecoder, -1);
    }

    public RedisCommand(String name, MultiDecoder<R> replayMultiDecoder, Convertor<R> convertor) {
        this(name, replayMultiDecoder, -1);
        this.convertor = convertor;
    }


    public RedisCommand(String name, MultiDecoder<R> replayMultiDecoder, int objectParamIndex) {
        this(name, null, replayMultiDecoder, null, objectParamIndex);
    }

    public RedisCommand(String name, String subName, MultiDecoder<R> replayMultiDecoder,
            int objectParamIndex) {
        this(name, subName, replayMultiDecoder, null, objectParamIndex);
    }

    public RedisCommand(String name, String subName, MultiDecoder<R> replayMultiDecoder, Decoder<R> reponseDecoder, int objectParamIndex) {
        super();
        this.name = name;
        this.subName = subName;
        this.replayMultiDecoder = replayMultiDecoder;
        this.replayDecoder = reponseDecoder;
        this.inParamIndex = objectParamIndex;
    }

    public String getSubName() {
        return subName;
    }

    public String getName() {
        return name;
    }

    public Decoder<R> getReplayDecoder() {
        return replayDecoder;
    }

    public int getInParamIndex() {
        return inParamIndex;
    }

    public MultiDecoder<R> getReplayMultiDecoder() {
        return replayMultiDecoder;
    }

    public Convertor<R> getConvertor() {
        return convertor;
    }

    public List<ValueType> getInParamType() {
        return inParamType;
    }

    public ValueType getOutParamType() {
        return outParamType;
    }

    @Override
    public String toString() {
        return "RedisCommand [name=" + name + ", subName=" + subName + "]";
    }

}

2. 严格命令细节封装 RedisStrictCommand

这个类是 RedisCommand 的子类。 上面看 RedisCommand 的代码可以看出, RedisCommand 提供了太多的构造函数。而 RedisStrictCommand 则提供几个很明确的构造函数,这几个构造函数明确参数名称、类型、解码器以及转换器等。

相比于父类,这些构造函数更加清晰明了。

package org.redisson.client.protocol;

import org.redisson.client.protocol.convertor.Convertor;
import org.redisson.client.protocol.decoder.MultiDecoder;

public class RedisStrictCommand<T> extends RedisCommand<T> {

    public RedisStrictCommand(String name, int objectParamIndex, ValueType inParamType) {
        super(name, (Decoder<T>)null, objectParamIndex, inParamType);
    }

    public RedisStrictCommand(String name, MultiDecoder<T> replayMultiDecoder) {
        super(name, replayMultiDecoder);
    }

    public RedisStrictCommand(String name, String subName, MultiDecoder<T> replayMultiDecoder) {
        super(name, subName, replayMultiDecoder, -1);
    }

    public RedisStrictCommand(String name) {
        super(name);
    }

    public RedisStrictCommand(String name, Convertor<T> convertor) {
        super(name, convertor, -1);
    }

    public RedisStrictCommand(String name, String subName, Convertor<T> convertor) {
        super(name, subName, convertor);
    }

    public RedisStrictCommand(String name, String subName, MultiDecoder<T> replayMultiDecoder, Convertor convertor) {
        super(name, subName, replayMultiDecoder, -1);
        this.convertor = convertor;
    }

    public RedisStrictCommand(String name, String subName, Decoder<T> reponseDecoder) {
        super(name, subName, null, reponseDecoder, -1);
    }

    public RedisStrictCommand(String name, Decoder<T> reponseDecoder) {
        super(name, reponseDecoder);
    }

}

3. Redis命令集合 RedisCommands

这个接口中声明了所有的 Redis 命令集合。 定义了命令的名称、参数数量、返回类型、返回类型解码器等。可以说是一个很核心的配置类,针对 Redis 返回的数据解码时需要从这里获取对应的解码器信息。

这个里面可以找到目前 Redisson 用到以及暂时没有用到的所有命令集合。

package org.redisson.client.protocol;

import java.util.List;
import java.util.Map;
import java.util.Set;

import org.redisson.client.protocol.RedisCommand.ValueType;
import org.redisson.client.protocol.convertor.BooleanAmountReplayConvertor;
import org.redisson.client.protocol.convertor.BooleanReplayConvertor;
import org.redisson.client.protocol.convertor.IntegerReplayConvertor;
import org.redisson.client.protocol.convertor.KeyValueConvertor;
import org.redisson.client.protocol.convertor.TrueReplayConvertor;
import org.redisson.client.protocol.convertor.VoidReplayConvertor;
import org.redisson.client.protocol.decoder.KeyValueObjectDecoder;
import org.redisson.client.protocol.decoder.ListScanResult;
import org.redisson.client.protocol.decoder.ListScanResultReplayDecoder;
import org.redisson.client.protocol.decoder.MapScanResult;
import org.redisson.client.protocol.decoder.MapScanResultReplayDecoder;
import org.redisson.client.protocol.decoder.NestedMultiDecoder;
import org.redisson.client.protocol.decoder.ObjectListReplayDecoder;
import org.redisson.client.protocol.decoder.ObjectMapReplayDecoder;
import org.redisson.client.protocol.decoder.ObjectSetReplayDecoder;
import org.redisson.client.protocol.decoder.StringDataDecoder;
import org.redisson.client.protocol.decoder.StringListReplayDecoder;
import org.redisson.client.protocol.decoder.StringMapDataDecoder;
import org.redisson.client.protocol.decoder.StringMapReplayDecoder;
import org.redisson.client.protocol.decoder.StringReplayDecoder;
import org.redisson.client.protocol.pubsub.PubSubStatusDecoder;

public interface RedisCommands {

    // 下面的命令都是 Redis 命令,以及对应的返回值解码器、转换器等。 查询 Redis 文档即可。
    RedisCommand<ListScanResult<String>> SCAN = new RedisCommand<ListScanResult<String>>("SCAN", new NestedMultiDecoder(new ObjectListReplayDecoder<String>(), new ListScanResultReplayDecoder()), ValueType.OBJECT);
    RedisStrictCommand<String> RANDOM_KEY = new RedisStrictCommand<String>("RANDOMKEY", new StringDataDecoder());
    RedisStrictCommand<String> PING = new RedisStrictCommand<String>("PING");

    RedisStrictCommand<Void> UNWATCH = new RedisStrictCommand<Void>("UNWATCH", new VoidReplayConvertor());
    RedisStrictCommand<Void> WATCH = new RedisStrictCommand<Void>("WATCH", new VoidReplayConvertor());
    RedisStrictCommand<Void> MULTI = new RedisStrictCommand<Void>("MULTI", new VoidReplayConvertor());
    RedisCommand<List<Object>> EXEC = new RedisCommand<List<Object>>("EXEC", new ObjectListReplayDecoder<Object>());

    RedisCommand<Long> SREM = new RedisCommand<Long>("SREM", 2, ValueType.OBJECTS);
    RedisCommand<Boolean> SADD = new RedisCommand<Boolean>("SADD", new BooleanAmountReplayConvertor(), 2, ValueType.OBJECTS);
    RedisCommand<Object> SPOP_SINGLE = new RedisCommand<Object>("SPOP");
    RedisCommand<Boolean> SADD_SINGLE = new RedisCommand<Boolean>("SADD", new BooleanReplayConvertor(), 2);
    RedisCommand<Boolean> SREM_SINGLE = new RedisCommand<Boolean>("SREM", new BooleanReplayConvertor(), 2);
    RedisCommand<List<Object>> SMEMBERS = new RedisCommand<List<Object>>("SMEMBERS", new ObjectListReplayDecoder<Object>());
    RedisCommand<ListScanResult<Object>> SSCAN = new RedisCommand<ListScanResult<Object>>("SSCAN", new NestedMultiDecoder(new ObjectListReplayDecoder<Object>(), new ListScanResultReplayDecoder()), ValueType.OBJECT);
    RedisCommand<Boolean> SISMEMBER = new RedisCommand<Boolean>("SISMEMBER", new BooleanReplayConvertor(), 2);
    RedisStrictCommand<Integer> SCARD = new RedisStrictCommand<Integer>("SCARD", new IntegerReplayConvertor());

    RedisCommand<Void> LSET = new RedisCommand<Void>("LSET", new VoidReplayConvertor(), 3);
    RedisCommand<Object> LPOP = new RedisCommand<Object>("LPOP");
    RedisCommand<Boolean> LREM_SINGLE = new RedisCommand<Boolean>("LREM", new BooleanReplayConvertor(), 3);
    RedisCommand<Long> LREM = new RedisCommand<Long>("LREM", 3);
    RedisCommand<Object> LINDEX = new RedisCommand<Object>("LINDEX");
    RedisCommand<Object> LINSERT = new RedisCommand<Object>("LINSERT", 3, ValueType.OBJECTS);
    RedisStrictCommand<Integer> LLEN = new RedisStrictCommand<Integer>("LLEN", new IntegerReplayConvertor());
    RedisStrictCommand<Boolean> LTRIM = new RedisStrictCommand<Boolean>("LTRIM", new BooleanReplayConvertor());

    RedisStrictCommand<Boolean> EXPIRE = new RedisStrictCommand<Boolean>("EXPIRE", new BooleanReplayConvertor());
    RedisStrictCommand<Boolean> EXPIREAT = new RedisStrictCommand<Boolean>("EXPIREAT", new BooleanReplayConvertor());
    RedisStrictCommand<Boolean> PERSIST = new RedisStrictCommand<Boolean>("PERSIST", new BooleanReplayConvertor());
    RedisStrictCommand<Long> TTL = new RedisStrictCommand<Long>("TTL");

    RedisCommand<Object> RPOPLPUSH = new RedisCommand<Object>("RPOPLPUSH");
    RedisCommand<Object> BRPOPLPUSH = new RedisCommand<Object>("BRPOPLPUSH");
    RedisCommand<Object> BLPOP = new RedisCommand<Object>("BLPOP", new KeyValueObjectDecoder());
    RedisCommand<Object> BLPOP_VALUE = new RedisCommand<Object>("BLPOP", new KeyValueObjectDecoder(), new KeyValueConvertor());

    RedisCommand<Boolean> PFADD = new RedisCommand<Boolean>("PFADD", new BooleanReplayConvertor(), 2);
    RedisCommand<Long> PFCOUNT = new RedisCommand<Long>("PFCOUNT");
    RedisStrictCommand<Void> PFMERGE = new RedisStrictCommand<Void>("PFMERGE", new VoidReplayConvertor());

    RedisCommand<Long> RPOP = new RedisCommand<Long>("RPOP");
    RedisCommand<Long> LPUSH = new RedisCommand<Long>("LPUSH");
    RedisCommand<List<Object>> LRANGE = new RedisCommand<List<Object>>("LRANGE", new ObjectListReplayDecoder<Object>());
    RedisCommand<Long> RPUSH = new RedisCommand<Long>("RPUSH", 2, ValueType.OBJECTS);
    RedisCommand<Boolean> RPUSH_BOOLEAN = new RedisCommand<Boolean>("RPUSH", new TrueReplayConvertor(), 2, ValueType.OBJECTS);

    RedisStrictCommand<String> SCRIPT_LOAD = new RedisStrictCommand<String>("SCRIPT", "LOAD", new StringDataDecoder());
    RedisStrictCommand<Boolean> SCRIPT_KILL = new RedisStrictCommand<Boolean>("SCRIPT", "KILL", new BooleanReplayConvertor());
    RedisStrictCommand<Boolean> SCRIPT_FLUSH = new RedisStrictCommand<Boolean>("SCRIPT", "FLUSH", new BooleanReplayConvertor());
    RedisStrictCommand<List<Boolean>> SCRIPT_EXISTS = new RedisStrictCommand<List<Boolean>>("SCRIPT", "EXISTS", new ObjectListReplayDecoder<Boolean>(), new BooleanReplayConvertor());

    RedisStrictCommand<Boolean> EVAL_BOOLEAN = new RedisStrictCommand<Boolean>("EVAL", new BooleanReplayConvertor());
    RedisStrictCommand<String> EVAL_STRING = new RedisStrictCommand<String>("EVAL", new StringReplayDecoder());
    RedisStrictCommand<Long> EVAL_INTEGER = new RedisStrictCommand<Long>("EVAL");
    RedisCommand<List<Object>> EVAL_LIST = new RedisCommand<List<Object>>("EVAL", new ObjectListReplayDecoder<Object>());
    RedisCommand<Object> EVAL_OBJECT = new RedisCommand<Object>("EVAL");
    RedisCommand<Object> EVAL_MAP_VALUE = new RedisCommand<Object>("EVAL", ValueType.MAP_VALUE);
    RedisCommand<List<Object>> EVAL_MAP_VALUE_LIST = new RedisCommand<List<Object>>("EVAL", new ObjectListReplayDecoder<Object>(), ValueType.MAP_VALUE);

    RedisStrictCommand<Long> INCR = new RedisStrictCommand<Long>("INCR");
    RedisStrictCommand<Long> INCRBY = new RedisStrictCommand<Long>("INCRBY");
    RedisStrictCommand<Long> DECR = new RedisStrictCommand<Long>("DECR");

    RedisStrictCommand<String> AUTH = new RedisStrictCommand<String>("AUTH", new StringReplayDecoder());
    RedisStrictCommand<String> SELECT = new RedisStrictCommand<String>("SELECT", new StringReplayDecoder());
    RedisStrictCommand<Boolean> CLIENT_SETNAME = new RedisStrictCommand<Boolean>("CLIENT", "SETNAME", new BooleanReplayConvertor());
    RedisStrictCommand<String> CLIENT_GETNAME = new RedisStrictCommand<String>("CLIENT", "GETNAME", new StringDataDecoder());
    RedisStrictCommand<Void> FLUSHDB = new RedisStrictCommand<Void>("FLUSHDB", new VoidReplayConvertor());
    RedisStrictCommand<Void> FLUSHALL = new RedisStrictCommand<Void>("FLUSHALL", new VoidReplayConvertor());

    RedisStrictCommand<List<String>> KEYS = new RedisStrictCommand<List<String>>("KEYS", new StringListReplayDecoder());

    RedisCommand<Boolean> HSET = new RedisCommand<Boolean>("HSET", new BooleanReplayConvertor(), 2, ValueType.MAP);
    RedisStrictCommand<String> HINCRBYFLOAT = new RedisStrictCommand<String>("HINCRBYFLOAT");
    RedisCommand<MapScanResult<Object, Object>> HSCAN = new RedisCommand<MapScanResult<Object, Object>>("HSCAN", new NestedMultiDecoder(new ObjectMapReplayDecoder(), new MapScanResultReplayDecoder()), ValueType.MAP);
    RedisCommand<Map<Object, Object>> HGETALL = new RedisCommand<Map<Object, Object>>("HGETALL", new ObjectMapReplayDecoder(), ValueType.MAP);
    RedisCommand<List<Object>> HVALS = new RedisCommand<List<Object>>("HVALS", new ObjectListReplayDecoder<Object>(), ValueType.MAP_VALUE);
    RedisCommand<Boolean> HEXISTS = new RedisCommand<Boolean>("HEXISTS", new BooleanReplayConvertor(), 2, ValueType.MAP_KEY);
    RedisStrictCommand<Integer> HLEN = new RedisStrictCommand<Integer>("HLEN", new IntegerReplayConvertor());
    RedisCommand<Set<Object>> HKEYS = new RedisCommand<Set<Object>>("HKEYS", new ObjectSetReplayDecoder(), ValueType.MAP_KEY);
    RedisCommand<String> HMSET = new RedisCommand<String>("HMSET", new StringReplayDecoder(), 1, ValueType.MAP);
    RedisCommand<List<Object>> HMGET = new RedisCommand<List<Object>>("HMGET", new ObjectListReplayDecoder<Object>(), 2, ValueType.MAP_KEY, ValueType.MAP_VALUE);
    RedisCommand<Object> HGET = new RedisCommand<Object>("HGET", 2, ValueType.MAP_KEY, ValueType.MAP_VALUE);
    RedisCommand<Long> HDEL = new RedisStrictCommand<Long>("HDEL", 2, ValueType.MAP_KEY);

    RedisStrictCommand<Long> DEL = new RedisStrictCommand<Long>("DEL");
    RedisStrictCommand<Boolean> DEL_SINGLE = new RedisStrictCommand<Boolean>("DEL", new BooleanReplayConvertor());

    RedisCommand<Object> GET = new RedisCommand<Object>("GET");
    RedisCommand<Void> SET = new RedisCommand<Void>("SET", new VoidReplayConvertor(), 2);
    RedisCommand<Boolean> SETNX = new RedisCommand<Boolean>("SETNX", new BooleanReplayConvertor(), 2);
    RedisCommand<Void> SETEX = new RedisCommand<Void>("SETEX", new VoidReplayConvertor(), 3);
    RedisStrictCommand<Boolean> EXISTS = new RedisStrictCommand<Boolean>("EXISTS", new BooleanReplayConvertor());

    RedisStrictCommand<Boolean> RENAMENX = new RedisStrictCommand<Boolean>("RENAMENX", new BooleanReplayConvertor());
    RedisStrictCommand<Void> RENAME = new RedisStrictCommand<Void>("RENAME", new VoidReplayConvertor());
    RedisStrictCommand<Boolean> MOVE = new RedisStrictCommand<Boolean>("MOVE", new BooleanReplayConvertor());
    RedisStrictCommand<Void> MIGRATE = new RedisStrictCommand<Void>("MIGRATE", new VoidReplayConvertor());

    RedisCommand<Long> PUBLISH = new RedisCommand<Long>("PUBLISH", 2);

    RedisCommand<Object> SUBSCRIBE = new RedisCommand<Object>("SUBSCRIBE", new PubSubStatusDecoder());
    RedisCommand<Object> UNSUBSCRIBE = new RedisCommand<Object>("UNSUBSCRIBE", new PubSubStatusDecoder());
    RedisCommand<Object> PSUBSCRIBE = new RedisCommand<Object>("PSUBSCRIBE", new PubSubStatusDecoder());
    RedisCommand<Object> PUNSUBSCRIBE = new RedisCommand<Object>("PUNSUBSCRIBE", new PubSubStatusDecoder());

    RedisStrictCommand<String> CLUSTER_NODES = new RedisStrictCommand<String>("CLUSTER", "NODES", new StringDataDecoder());
    RedisStrictCommand<Map<String, String>> CLUSTER_INFO = new RedisStrictCommand<Map<String, String>>("CLUSTER", "INFO", new StringMapDataDecoder());

    RedisStrictCommand<List<String>> SENTINEL_GET_MASTER_ADDR_BY_NAME = new RedisStrictCommand<List<String>>("SENTINEL", "GET-MASTER-ADDR-BY-NAME", new StringListReplayDecoder());
    RedisStrictCommand<List<Map<String, String>>> SENTINEL_SLAVES = new RedisStrictCommand<List<Map<String, String>>>("SENTINEL", "SLAVES", new StringMapReplayDecoder());

}

4. 命令执行数据 CommandData

类用于封装一个 Redis 命令的所有相关数据,包括命令本身、参数、编码解码器以及异步结果处理。

package org.redisson.client.protocol;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.redisson.client.codec.Codec;
import org.redisson.client.protocol.decoder.MultiDecoder;

import io.netty.util.concurrent.Promise;

public class CommandData<T, R> implements QueueCommand {

    final Promise<R> promise;   // 表示异步操作的结果
    final RedisCommand<T> command; // 要执行的 Redis 命令
    final Object[] params; // Redis命令参数
    final Codec codec; // 编解码器
    final MultiDecoder<Object> messageDecoder; // 处理 Redis 返回的复杂响应解码器。 比如 MULTI 命令的结果

    public CommandData(Promise<R> promise, Codec codec, RedisCommand<T> command, Object[] params) {
        this(promise, null, codec, command, params);
    }

    public CommandData(Promise<R> promise, MultiDecoder<Object> messageDecoder, Codec codec, RedisCommand<T> command, Object[] params) {
        this.promise = promise;
        this.command = command;
        this.params = params;
        this.codec = codec;
        this.messageDecoder = messageDecoder;
    }

    public RedisCommand<T> getCommand() {
        return command;
    }

    public Object[] getParams() {
        return params;
    }

    public MultiDecoder<Object> getMessageDecoder() {
        return messageDecoder;
    }

    public Promise<R> getPromise() {
        return promise;
    }

    public Codec getCodec() {
        return codec;
    }

    @Override
    public String toString() {
        return "CommandData [promise=" + promise + ", command=" + command + ", params="
                + Arrays.toString(params) + ", codec=" + codec + "]";
    }

    @Override
    public List<CommandData<Object, Object>> getPubSubOperations() {
        // 如果是发布订阅相关的命令,才会有返回值
        if (Arrays.asList("PSUBSCRIBE", "SUBSCRIBE", "PUNSUBSCRIBE", "UNSUBSCRIBE")
                .contains(getCommand().getName())) {
            return Collections.singletonList((CommandData<Object, Object>)this);
        }
        return Collections.emptyList();
    }

}

5. 一组命令执行数据 CommandsData

封装一组 Redis 命令,支持批量处理。 在Redisson库中用于执行多个命令的场景。

package org.redisson.client.protocol;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import io.netty.util.concurrent.Promise;

public class CommandsData implements QueueCommand {

    private final List<CommandData<?, ?>> commands;  // 存储一批命令
    private final Promise<Void> promise;  // 异步操作的结果

    public CommandsData(Promise<Void> promise, List<CommandData<?, ?>> commands) {
        super();
        this.promise = promise;
        this.commands = commands;
    }

    public Promise<Void> getPromise() {
        return promise;
    }

    public List<CommandData<?, ?>> getCommands() {
        return commands;
    }

    @Override
    public List<CommandData<Object, Object>> getPubSubOperations() {
        // 储符合条件的 CommandData 对象
        List<CommandData<Object, Object>> result = new ArrayList<CommandData<Object, Object>>();
        for (CommandData<?, ?> commandData : commands) {
            // 检查当前命令是否是订阅或取消订阅命令
            if (Arrays.asList("PSUBSCRIBE", "SUBSCRIBE", "PUNSUBSCRIBE", "UNSUBSCRIBE")
                    .equals(commandData.getCommand().getName())) {
                result.add((CommandData<Object, Object>)commandData);
            }
        }
        // 返回符合条件的数据
        return result;
    }

}