这是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.
* <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