Jedis源码解析——Jedis和BinaryJedis

一、基本信息

先来看看他们的类定义:java

public class Jedis extends BinaryJedis implements JedisCommands, MultiKeyCommands, AdvancedJedisCommands, ScriptingCommands, BasicCommands, ClusterCommands, SentinelCommands {
    ……
    }

public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKeyBinaryCommands, AdvancedBinaryJedisCommands, BinaryScriptingCommands, Closeable {
    ……
    }

Jedis继承自BinaryJedis,两者都实现了一系列的命令接口。redis

仔细看就能发现,这些接口几乎是一一对应的:例如MultiKeyBinaryCommands和MultiKeyCommands,BinaryScriptingCommands和ScriptingCommands等等。从名字就能够看出来他们之间的区别就是是不是binary(二进制)的,从他们的各自的方法中能够找到依据。markdown

public interface MultiKeyBinaryCommands {
  Long del(byte[]... keys);

  List<byte[]> blpop(int timeout, byte[]... keys);

  List<byte[]> brpop(int timeout, byte[]... keys);

  List<byte[]> blpop(byte[]... args);

  List<byte[]> brpop(byte[]... args);

  Set<byte[]> keys(byte[] pattern);
  ……

}

public interface MultiKeyCommands {
  Long del(String... keys);

  List<String> blpop(int timeout, String... keys);

  List<String> brpop(int timeout, String... keys);

  List<String> blpop(String... args);

  List<String> brpop(String... args);

  Set<String> keys(String pattern);

……

}

这些接口命令中,只有BasicCommands是相同的,不存在是否是二进制相关的方法。由于该类中主要是redis的其余操做,并不涉及具体数据类型的操做。简单看几个方法就知道了。socket

public interface BasicCommands {

  String ping();

  String quit();

  String flushDB();

  Long dbSize();

  String select(int index);

  String flushAll();

  String auth(String password);
……
}

二、结构关系

前面介绍完了两个类之间的关系和实现的接口,虽然咱们日常使用以jedis居多,但其实精华都在binaryJedis中。函数

//真正的客户端
 protected Client client = null;
 //用来区分是不是事务操做
  protected Transaction transaction = null;
  protected Pipeline pipeline = null;

//下面列举了几种比较典型的构造方法

  public BinaryJedis() {
    client = new Client();
  }

  public BinaryJedis(final String host) {
    URI uri = URI.create(host);
    if (uri.getScheme() != null && uri.getScheme().equals("redis")) {
      initializeClientFromURI(uri);
    } else {
      client = new Client(host);
    }
  }


  public BinaryJedis(final String host, final int port, final int connectionTimeout,
      final int soTimeout) {
    client = new Client(host, port);
    client.setConnectionTimeout(connectionTimeout);
    client.setSoTimeout(soTimeout);
  }

  public BinaryJedis(final JedisShardInfo shardInfo) {
    client = new Client(shardInfo.getHost(), shardInfo.getPort());
    client.setConnectionTimeout(shardInfo.getConnectionTimeout());
    client.setSoTimeout(shardInfo.getSoTimeout());
    client.setPassword(shardInfo.getPassword());
    client.setDb(shardInfo.getDb());
  }


  public BinaryJedis(final URI uri, final int timeout) {
    initializeClientFromURI(uri);
    client.setConnectionTimeout(timeout);
    client.setSoTimeout(timeout);
  }

构造函数中的操做,基本上都是建立Client,并初始化数据信息。那么这个Client是个什么呢?ui

这里写图片描述

public class Client extends BinaryClient implements Commands {}

public class BinaryClient extends Connection {}

Tips:Client与BinaryClient的区别:BinaryClient是原生客户端,而Client封装性更好,也被叫作高级客户端。spa

Connection类中主要是socket进行通讯,一个Connection已经就是一个最基础的客户端。code

另外增长各类协议层次的发送命令和收取结果的方法,都是经过Protocol类的操做RedisOutputStream和RedisInputStream完成的。封装了输入输出流,来方便使用。继承

public class Connection implements Closeable {

  private String host = Protocol.DEFAULT_HOST;
  private int port = Protocol.DEFAULT_PORT;
  private Socket socket;
  private RedisOutputStream outputStream;
  private RedisInputStream inputStream;
  ……
  }

主要方法:接口

一、connect()

public void connect() {
    if (!isConnected()) {
      try {
      //建立socket,设置相关参数
        socket = new Socket();
        socket.setReuseAddress(true);
        socket.setKeepAlive(true); // Will monitor the TCP connection is
        // valid
        socket.setTcpNoDelay(true); // Socket buffer Whetherclosed, to
        // ensure timely delivery of data
        socket.setSoLinger(true, 0); // Control calls close () method,
        // 链接
        socket.connect(new InetSocketAddress(host, port), connectionTimeout);
        socket.setSoTimeout(soTimeout);
        //输入输出
        outputStream = new RedisOutputStream(socket.getOutputStream());
        inputStream = new RedisInputStream(socket.getInputStream());
      } catch (IOException ex) {
        broken = true;
        throw new JedisConnectionException(ex);
      }
    }
  }

二、disconnect()

public void disconnect() {
    if (isConnected()) {
      try {
        outputStream.flush();
        socket.close();
      } catch (IOException ex) {
        broken = true;
        throw new JedisConnectionException(ex);
      } finally {
        IOUtils.closeQuietly(socket);
      }
    }
  }

三、isConnected()

public boolean isConnected() {
    return socket != null && socket.isBound() && !socket.isClosed() && socket.isConnected()
        && !socket.isInputShutdown() && !socket.isOutputShutdown();
  }
相关文章
相关标签/搜索