这是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 // <-@wjw_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. ** 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,更深入的理解。
关于soTimeout 与 connectionTimeOut
我不多说了,这个链接解释非常清楚。