zoukankan      html  css  js  c++  java
  • Jedis源码解析——Jedis和BinaryJedis

    1、基本信息

    先来看看他们的类定义:

    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,二者都实现了一系列的命令接口。

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

    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的其他操作,并不涉及具体数据类型的操作。简单看几个方法就知道了。

    public interface BasicCommands {
    
      String ping();
    
      String quit();
    
      String flushDB();
    
      Long dbSize();
    
      String select(int index);
    
      String flushAll();
    
      String auth(String password);
    ……
    }

    2、结构关系

    前面介绍完了两个类之间的关系和实现的接口,虽然我们平常使用以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是个什么呢?

    这里写图片描述

    public class Client extends BinaryClient implements Commands {}
    
    public class BinaryClient extends Connection {}

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

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

    另外增加各种协议层次的发送命令和收取结果的方法,都是通过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;
      ……
      }

    主要方法:

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

    2、disconnect()

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

    3、isConnected()

      public boolean isConnected() {
        return socket != null && socket.isBound() && !socket.isClosed() && socket.isConnected()
            && !socket.isInputShutdown() && !socket.isOutputShutdown();
      }
  • 相关阅读:
    为什么说 Mybatis 是半自动 ORM 映射工具?它与全自动的区别在哪里?
    http的响应码200,404,302,500表示的含义分别是?
    说一下 session 的工作原理?
    session 和 cookie 有什么区别?
    什么是 MyBatis?
    SpringMVC 工作原理?
    报表数据填报中的合法性校验
    报表数据填报中的自动计算
    如何用报表工具实现树状层级结构的填报表
    在报表中录入数据时如何实现行列转换
  • 原文地址:https://www.cnblogs.com/saixing/p/6730195.html
Copyright © 2011-2022 走看看