Preface
Jedis is the preferred client for java application to access Redis service. This paper analyses the source code of jedis client, and picks up the common routine of client design and implementation.
Connection
To access (Redis) services, you first need to establish a connection with the service, so the client library first needs to abstract and encapsulate the connection. Jedis uses the Connection class to encapsulate a socket connection with the server:
public class Connection implements Closable { private Socket socket; private connectionTimeout = Protocol.DEFAULT_TIMEOUT; private int soTimeout = Protocol.DEFAULT_TIMEOUT; ... public Connection() {} public Connection(final String host) { this.host = host; } public Connection(final String host, final int port) { this.host = host; this.port = port; } }
Usually, the Connection class also encapsulates the read and write of socket s. For the Redis client, it sends commands and gets results. Here, the Command class is an enumeration type of commands, and args is a variable length parameter, representing command parameters.
protected Connection sendCommand(final Command cmd, final byte[]... args) { // See below }
Due to the instability of network communication, the communication between client and server usually needs to catch various exceptions and recover (retry, reconnect)
// sendCommand Implementation try { connect(); Protocol.sendCommand(outputStream, cmd, args); pipelinedCommands++; return this; } catch (JedisConnectionException ex) { try { String errorMessage = Protocol.readErrorLineIfPossible(inputStream); if (errorMessage != null && errorMessage.length() > 0) { ex = new JedisConnectionException(errorMessage, ex.getCause()); } } catch (Exception e) { } // Any other exceptions related to connection? broken = true; throw ex; }
The connect method establishes the connection, which is not necessary if the connection has been established. Here are some common parameters of socket.
reuse address
keep alive
tcp no delay
so linger
so timeout
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); } } }
Input, output stream
Protocol
Socket connection establishes a communication channel between client and server. Protocol specifies the data transmission format. For Redis, a service using long socket connection, the protocol is usually customized, so the protocol should be abstracted and encapsulated next.