1. 程式人生 > >Jedis 源代碼閱讀一 —— Jedis

Jedis 源代碼閱讀一 —— Jedis

hide ensure live vra stack override boolean soc node

這是jedis 源代碼文件夾,我們接下來選擇性閱讀重要的接口以及實現。

└─redis
    └─clients
        ├─jedis
        │  │  BinaryClient.java
        │  │  BinaryJedis.java
        │  │  BinaryJedisCluster.java
        │  │  BinaryJedisPubSub.java
        │  │  BinaryShardedJedis.java
        │  │  BitOP.java
        │  │  BitPosParams.java
│ │ Builder.java │ │ BuilderFactory.java │ │ Client.java │ │ Connection.java │ │ DebugParams.java │ │ GeoCoordinate.java │ │ GeoRadiusResponse.java │ │ GeoUnit.java │ │ HostAndPort.java │ │ Jedis.java
│ │ JedisCluster.java │ │ JedisClusterCommand.java │ │ JedisClusterConnectionHandler.java │ │ JedisClusterInfoCache.java │ │ JedisFactory.java │ │ JedisMonitor.java │ │ JedisPool.java │ │ JedisPoolAbstract.java │ │ JedisPoolConfig.java
│ │ JedisPubSub.java │ │ JedisSentinelPool.java │ │ JedisShardInfo.java │ │ JedisSlotBasedConnectionHandler.java │ │ MultiKeyPipelineBase.java │ │ Pipeline.java │ │ PipelineBase.java │ │ Protocol.java │ │ Queable.java │ │ Response.java │ │ ScanParams.java │ │ ScanResult.java │ │ ShardedJedis.java │ │ ShardedJedisPipeline.java │ │ ShardedJedisPool.java │ │ SortingParams.java │ │ Transaction.java │ │ Tuple.java │ │ ZParams.java │ │ │ ├─commands │ │ AdvancedBinaryJedisCommands.java │ │ AdvancedJedisCommands.java │ │ BasicCommands.java │ │ BasicRedisPipeline.java │ │ BinaryJedisClusterCommands.java │ │ BinaryJedisCommands.java │ │ BinaryRedisPipeline.java │ │ BinaryScriptingCommands.java │ │ BinaryScriptingCommandsPipeline.java │ │ ClusterCommands.java │ │ ClusterPipeline.java │ │ Commands.java │ │ JedisClusterBinaryScriptingCommands.java │ │ JedisClusterCommands.java │ │ JedisClusterScriptingCommands.java │ │ JedisCommands.java │ │ MultiKeyBinaryCommands.java │ │ MultiKeyBinaryJedisClusterCommands.java │ │ MultiKeyBinaryRedisPipeline.java │ │ MultiKeyCommands.java │ │ MultiKeyCommandsPipeline.java │ │ MultiKeyJedisClusterCommands.java │ │ ProtocolCommand.java │ │ RedisPipeline.java │ │ ScriptingCommands.java │ │ ScriptingCommandsPipeline.java │ │ SentinelCommands.java │ │ │ ├─exceptions │ │ InvalidURIException.java │ │ JedisAskDataException.java │ │ JedisClusterCrossSlotException.java │ │ JedisClusterException.java │ │ JedisClusterMaxRedirectionsException.java │ │ JedisConnectionException.java │ │ JedisDataException.java │ │ JedisException.java │ │ JedisMovedDataException.java │ │ JedisRedirectionException.java │ │ │ └─params │ │ Params.java │ │ │ ├─geo │ │ GeoRadiusParam.java │ │ │ ├─set │ │ SetParams.java │ │ │ └─sortedset │ ZAddParams.java │ ZIncrByParams.java │ └─util ClusterNodeInformation.java ClusterNodeInformationParser.java Hashing.java IOUtils.java JedisByteHashMap.java JedisClusterCRC16.java JedisURIHelper.java KeyMergeUtil.java MurmurHash.java Pool.java RedisInputStream.java RedisOutputStream.java SafeEncoder.java Sharded.java ShardInfo.java Slowlog.java

Jedis.java

技術分享
我們每次使用jedis都會初始化一個jedis對象,對下面代碼肯定不會陌生:

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

  protected JedisPoolAbstract dataSource = null;

  public Jedis() {
    super();
  }

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

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

Jedis對象調用父類BinaryJedis構造器:

public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKeyBinaryCommands,
        AdvancedBinaryJedisCommands, BinaryScriptingCommands, Closeable {
    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);
    }

實際上,new Jedis()的初始化中。最重要的是new Client()這句代碼。


Client 繼承自 BinaryClient

public class Client extends BinaryClient implements Commands {

  public Client() {
    super();
  }

而BinaryClient又繼承自Collection


public class BinaryClient extends Connection {
 ............
  private String password;

  private int db;

  private boolean isInWatch;

............
  public BinaryClient() {
    super();
  }
............

接著我們來看Collection代碼:

    public class Connection implements Closeable {
    .....
    protected Connection sendCommand(final ProtocolCommand cmd, final String... args) {
        final byte[][] bargs = new byte[args.length][];
        for (int i = 0; i < args.length; i++) {
            // 對cmd判空並返回bytes
            bargs[i] = SafeEncoder.encode(args[i]);
        }
        return sendCommand(cmd, bargs);
    }

    protected Connection sendCommand(final ProtocolCommand cmd) {
        return sendCommand(cmd, EMPTY_ARGS);
    }

    protected Connection sendCommand(final ProtocolCommand cmd, final byte[]... args) {
        try {
            // 1.建立Socket連接
            connect();
            // 2.依照協議完畢IO操作,也就是命令的運行
            Protocol.sendCommand(outputStream, cmd, args);
            return this;
        } 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; } } ... // 建立Sock連接 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 // <[email protected]_add 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); } } } ...

在這裏完畢了Socket連接。並返回這個Socket.
技術分享
每次我們使用Jedis去運行命令。都是這個持有Soket的client去運行的。


比方:

    /**
     * Get the value of the specified key. If the key does not exist null is
     * returned. If the value stored at key is not a string an error is returned
     * because GET can only handle string values.
     * <p>
     * Time complexity: O(1)
     * 
     * @param key
     * @return Bulk reply
     */
    @Override
    public String get(final String key) {
        checkIsInMultiOrPipeline();// 檢查是否在事物中;檢查是否是喲好難過管道技術
        client.sendCommand(Protocol.Command.GET, key);// 使用Socket進行IO操作,運行命令
        return client.getBulkReply();
    }

jedis除了繼承的BinaryJedis完畢主要的IO操作。還實現了 JedisCommands, MultiKeyCommands, AdvancedJedisCommands,ScriptingCommands, BasicCommands, ClusterCommands, SentinelCommands
這幾個可使用的命令的接口。

你能夠參考redis自帶的 unitTest,更深入的理解。


http://download.csdn.net/detail/lemon89/9407039

關於soTimeout 與 connectionTimeOut

我不多說了,這個鏈接解釋非常清楚。

http://stackoverflow.com/questions/7360520/connectiontimeout-versus-sockettimeout

Jedis 源代碼閱讀一 —— Jedis