jedis取存 数据库查到的对象_Jedis与Redis数据库的链接建立

b9d8dc5da9c18a4a1c5a4971b13e94be.png
// 连接本地的Redis服务
Jedis jedis = new Jedis("127.0.0.1", 6379);
		
// 存储List缓存数据
jedis.lpush("test-list", "Java");
jedis.lpush("test-list", "PHP");
jedis.lpush("test-list", "C++");

// 获取list缓存数据
List<String> listCache = jedis.lrange("test-list", 0, 3);
for (int i = 0; i < listCache.size(); i++)
{
	System.out.println("缓存输出:" + listCache.get(i));
}

jedis.close();

我们直到,redis是走网络通信的数据库,应用程序与redis的交互需要进行网络通信。

当我们使用jedis的操作命令与数据库交互时,具体都发生了什么呢?

public Jedis()
{
	super();
}

public Jedis(final String host)
{
	super(host);
}

public Jedis(final String host, final int port)
{
	super(host, port);
}

public Jedis(final String host, final int port, final int timeout)
{
	super(host, port, timeout);
}

public Jedis(final String host, final int port, final int connectionTimeout, 
final int soTimeout)
{
	super(host, port, connectionTimeout, soTimeout);
}

此时super调用的父类是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)
{
	client = new Client(host, port);
}

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

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);
}

到这里就会发现与redis进行网络通信的类就是Client类,继续向上发现:

Connection<<BinaryClient<<Client类的继承关系

public class Client extends BinaryClient implements Commands {

  public Client() {
    super();
  }

  public Client(final String host) {
    super(host);
  }

  public Client(final String host, final int port) {
    super(host, port);
  }

  ..........................................................
}
public class BinaryClient extends Connection {

  private boolean isInMulti;

  private String password;

  private int db;

  private boolean isInWatch;

  public BinaryClient() {
    super();
  }

  public BinaryClient(final String host) {
    super(host);
  }

  public BinaryClient(final String host, final int port) {
    super(host, port);
  }

  public BinaryClient(final String host, final int port, final boolean ssl) {
    super(host, port, ssl);
  }
  ...............
}
public class Connection implements Closeable {

  private static final byte[][] EMPTY_ARGS = new byte[0][];

  private String host = Protocol.DEFAULT_HOST;
  private int port = Protocol.DEFAULT_PORT;
  private Socket socket;
  private RedisOutputStream outputStream;
  private RedisInputStream inputStream;
  private int connectionTimeout = Protocol.DEFAULT_TIMEOUT;
  private int soTimeout = Protocol.DEFAULT_TIMEOUT;
  private boolean broken = false;
  private boolean ssl;
  private SSLSocketFactory sslSocketFactory;
  private SSLParameters sslParameters;
  private HostnameVerifier hostnameVerifier;

  public Connection() {
  }

  public Connection(final String host) {
    this.host = host;
  }

  public Connection(final String host, final int port) {
    this.host = host;
    this.port = port;
  }

  public Connection(final String host, final int port, final boolean ssl) {
    this.host = host;
    this.port = port;
    this.ssl = ssl;
  }

  public Connection(final String host, final int port, final boolean ssl,
      SSLSocketFactory sslSocketFactory, SSLParameters sslParameters,
      HostnameVerifier hostnameVerifier) {
    this.host = host;
    this.port = port;
    this.ssl = ssl;
    this.sslSocketFactory = sslSocketFactory;
    this.sslParameters = sslParameters;
    this.hostnameVerifier = hostnameVerifier;
  }
  .................................................................
}

可以看到创建Jedis对象的时候并没有进行真正的网络连接,那么什么时候才执行的呢?

/**
* 获取特定键对应的值.如果键不存在,会返回null.如果存储在该关键字上的值不是一个字符串,
将会返回错误,因为get只能处理字符串类型。
* 
* 时间复杂度: O(1)
* 
* @param key
* @return Bulk reply
*/
public String get(final String key)
{
	checkIsInMultiOrPipeline();
	client.sendCommand(Protocol.Command.GET, key);
	return client.getBulkReply();
}

上述方法是Jedis对象当中的一个普通方法,client对象最终会调用sendCommand方法来发送协议查询key所对应的value数据。

sendCommand方法是继承自Connection的,

 public void sendCommand(final ProtocolCommand cmd, final String... args) {
    final byte[][] bargs = new byte[args.length][];
    for (int i = 0; i < args.length; i++) {
      bargs[i] = SafeEncoder.encode(args[i]);
    }
    sendCommand(cmd, bargs);
  }

  public void sendCommand(final ProtocolCommand cmd) {
    sendCommand(cmd, EMPTY_ARGS);
  }

  public void sendCommand(final ProtocolCommand cmd, final byte[]... args) {
    try {
      connect();
      Protocol.sendCommand(outputStream, cmd, args);
    } catch (JedisConnectionException ex) {
      /*
       * When client send request which formed by invalid protocol, Redis send back error message
       * before close connection. We try to read it to provide reason of failure.
       */
      try {
        String errorMessage = Protocol.readErrorLineIfPossible(inputStream);
        if (errorMessage != null && errorMessage.length() > 0) {
          ex = new JedisConnectionException(errorMessage, ex.getCause());
        }
      } catch (Exception e) {
        /*
         * Catch any IOException or JedisConnectionException occurred from InputStream#read and just
         * ignore. This approach is safe because reading error message is optional and connection
         * will eventually be closed.
         */
      }
      // Any other exceptions related to connection?
      broken = true;
      throw ex;
    }
  }

  public String getHost() {
    return host;
  }

  public void setHost(final String host) {
    this.host = host;
  }

  public int getPort() {
    return port;
  }

  public void setPort(final int port) {
    this.port = port;
  }

  public void connect() {
    if (!isConnected()) {
      try {
        socket = new Socket();
        // ->@wjw_add
        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,
        // the underlying socket is closed
        // immediately
        // <-@wjw_add

        socket.connect(new InetSocketAddress(host, port), connectionTimeout);
        socket.setSoTimeout(soTimeout);

        if (ssl) {
          if (null == sslSocketFactory) {
            sslSocketFactory = (SSLSocketFactory)SSLSocketFactory.getDefault();
          }
          socket = sslSocketFactory.createSocket(socket, host, port, true);
          if (null != sslParameters) {
            ((SSLSocket) socket).setSSLParameters(sslParameters);
          }
          if ((null != hostnameVerifier) &&
              (!hostnameVerifier.verify(host, ((SSLSocket) socket).getSession()))) {
            String message = String.format(
                "The connection to '%s' failed ssl/tls hostname verification.", host);
            throw new JedisConnectionException(message);
          }
        }

        outputStream = new RedisOutputStream(socket.getOutputStream());
        inputStream = new RedisInputStream(socket.getInputStream());
      } catch (IOException ex) {
        broken = true;
        throw new JedisConnectionException("Failed connecting to host " 
            + host + ":" + port, ex);
      }
    }
  }

  @Override
  public void close() {
    disconnect();
  }

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

我们可以看到是在使用的时候才真正执行网络连接的。

---------

但是如果我们是采用JedisPool的形式来获取Jedis对象,那么其实在获取Jedis对象的时候就进行了网络连接操作;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值