Redis client Jedis and Jedis operation Redis command detailed explanation: http://donald-draper.iteye.com/blog/2347192
Spring and Redis Integration Details 1: http://donald-draper.iteye.com/blog/2347337
In the last article, we analyzed the Jedis connection factory to create the redis connection JedisConnection, and the RedisTemplate to execute the Redis callback interface method.
Today, let's take a look at the RedisTemplate related Set value method
public class RedisTemplate extends RedisAccessor implements RedisOperations { private boolean exposeConnection; private RedisSerializer defaultSerializer; private RedisSerializer keySerializer; private RedisSerializer valueSerializer; private RedisSerializer hashKeySerializer; private RedisSerializer hashValueSerializer; private RedisSerializer stringSerializer; private ValueOperations valueOps; private ListOperations listOps; private SetOperations setOps; private ZSetOperations zSetOps; public RedisTemplate() { exposeConnection = false; defaultSerializer = new JdkSerializationRedisSerializer(); keySerializer = null; valueSerializer = null; hashKeySerializer = null; hashValueSerializer = null; stringSerializer = new StringRedisSerializer(); } //Serialize the string, which we saw in the previous article private byte[] rawString(String key) { return stringSerializer.serialize(key); } // delete key public void delete(Object key) { final byte rawKey[] = rawKey(key); execute(new RedisCallback() { //From the previous analysis, the connection is actually JedisConnection public Object doInRedis(RedisConnection connection) { connection.del(new byte[][] { rawKey }); return null; } final byte val$rawKey[]; final RedisTemplate this$0; { this$0 = RedisTemplate.this; rawKey = abyte0; super(); } }, true); } // set expiration time public Boolean expire(Object key, long timeout, TimeUnit unit) { final byte rawKey[] = rawKey(key); final long rawTimeout = unit.toSeconds(timeout); return (Boolean)execute(new RedisCallback() { public Boolean doInRedis(RedisConnection connection) { return connection.expire(rawKey, rawTimeout); } public volatile Object doInRedis(RedisConnection x0) throws DataAccessException { return doInRedis(x0); } final byte val$rawKey[]; final long val$rawTimeout; final RedisTemplate this$0; { this$0 = RedisTemplate.this; rawKey = abyte0; rawTimeout = l; super(); } }, true); } //Recommand key public void rename(Object oldKey, Object newKey) { final byte rawOldKey[] = rawKey(oldKey); final byte rawNewKey[] = rawKey(newKey); execute(new RedisCallback() { public Object doInRedis(RedisConnection connection) { connection.rename(rawOldKey, rawNewKey); return null; } final byte val$rawOldKey[]; final byte val$rawNewKey[]; final RedisTemplate this$0; { this$0 = RedisTemplate.this; rawOldKey = abyte0; rawNewKey = abyte1; super(); } }, true); } // start the transaction public void multi() { execute(new RedisCallback() { public Object doInRedis(RedisConnection connection) throws DataAccessException { connection.multi(); return null; } final RedisTemplate this$0; { this$0 = RedisTemplate.this; super(); } }, true); } }
The key-related operations from RedisTemplate are encapsulated in the Redis callback interface and then executed.
We're looking at JedisConnection
public class JedisConnection implements RedisConnection { private static final Field CLIENT_FIELD; private static final Method SEND_COMMAND;//Send command method private static final Method GET_RESPONSE; private final Jedis jedis;//jedis连接 private final Client client;//socket client of jedis and redis private final BinaryTransaction transaction;//事务 private final Pool pool;//Jedis connection pool private boolean broken; private volatile JedisSubscription subscription; private volatile Pipeline pipeline;//管道 private final int dbIndex;//Database static { //Get the Client property of BinaryJedis through the reflection tool CLIENT_FIELD = ReflectionUtils.findField(redis/clients/jedis/BinaryJedis, "client", redis/clients/jedis/Client); ReflectionUtils.makeAccessible(CLIENT_FIELD); //Get Jedis's Connection send command method SEND_COMMAND = ReflectionUtils.findMethod(redis/clients/jedis/Connection, "sendCommand", new Class[] { redis/clients/jedis/Protocol$Command, [[B }); ReflectionUtils.makeAccessible(SEND_COMMAND); //The method of Jedis's Connection to get the result of redis reply GET_RESPONSE = ReflectionUtils.findMethod(redis/clients/jedis/Queable, "getResponse", new Class[] { redis/clients/jedis/Builder }); ReflectionUtils.makeAccessible(GET_RESPONSE); } public JedisConnection(Jedis jedis, Pool pool, int dbIndex) { broken = false; this.jedis = jedis; //Get the Client property of Jedis client = (Client)ReflectionUtils.getField(CLIENT_FIELD, jedis); //set the transaction transaction = new Transaction(client); //connection pool this.pool = pool; //database this.dbIndex = dbIndex; if(dbIndex > 0) // switch database select(dbIndex); } }
//Transaction
public class Transaction extends BinaryTransaction { public Transaction(Client client) { great(customer); } //Set key expiration time public Response expire(String key, int seconds) { client.expire(key, seconds); return getResponse(BuilderFactory.LONG); } //get key value public Response get(String key) { client.get(key); return getResponse(BuilderFactory.STRING); } }
Look at BinaryTransaction again
public class BinaryTransaction extends Queable { protected Client client;//redis client protected boolean inTransaction;//Whether it is a transaction public BinaryTransaction(Client client) { this.client = null; inTransaction = true; this.client = client; } public Response setnx(byte key[], byte value[]) { client.setnx(key, value); return getResponse(BuilderFactory.LONG); } }
//Queable
public class Queable { private Queue pipelinedResponses;//Actually LinkedList public Queable() { pipelinedResponses = new LinkedList(); } protected void clean() { pipelinedResponses.clear(); } protected Response generateResponse(Object data) { Response response = (Response)pipelinedResponses.poll(); if(response != null) response.set(data); return response; } //When the transaction is open, add the result returned by Redis to the queue protected Response getResponse(Builder builder) { Response lr = new Response(builder); pipelinedResponses.add(lr); return lr; } }
Let's take a look at the related methods of JedisConnection
//whether it is a transaction public boolean isQueueing() { return client.isInMulti(); } //open the pipe public void openPipeline() { if(pipeline == null) pipeline = jedis.pipelined(); } //refresh DB public void flushDb() { try { if(isQueueing()) transaction.flushDB(); if(isPipelined()) pipeline.flushDB(); jedis.flushDB(); } catch(Exception ex) { throw convertJedisAccessException(ex); } } //Dump database public void bgSave() { try { if(isQueueing()) throw new UnsupportedOperationException(); if(isPipelined()) { pipeline.bgsave(); return; } } catch(Exception ex) { throw convertJedisAccessException(ex); } jedis.bgsave(); } //write AOP public void bgWriteAof() { try { if(isQueueing()) throw new UnsupportedOperationException(); if(isPipelined()) { pipeline.bgrewriteaof(); return; } } catch(Exception ex) { throw convertJedisAccessException(ex); } jedis.bgrewriteaof(); } // start the transaction public void multi() { if(isQueueing()) return; try { if(isPipelined()) { pipeline.multi(); return; } } catch(Exception ex) { throw convertJedisAccessException(ex); } jedis.multi(); } //set if key does not exist public Boolean setNX(byte key[], byte value[]) { if(!isQueueing()) break MISSING_BLOCK_LABEL_19; transaction.setnx(key, value); return null; if(!isPipelined()) break MISSING_BLOCK_LABEL_38; pipeline.setnx(key, value); return null; return JedisUtils.convertCodeReply(jedis.setnx(key, value)); Exception ex; ex; throw convertJedisAccessException(ex); }
From the analysis of the JedisConnection method, it can be seen that the related methods of JedisConnection rely on Jedis, Cclient and Transaction;
summary:
RedisTemplate's key related operations are encapsulated in the Redis callback interface, and then executed;
JedisConnection related methods are based on Jedis, Cclient and Transaction.
//Response
class Response { protected Object response; private boolean built; private boolean set; private Builder builder; private Object data; public Response(Builder b) { response = null; built = false; set = false; builder = b; } public void set(Object data) { this.data = data; set = true; } public Object get() { if(!set) throw new JedisDataException("Please close pipeline or multi block before calling this method."); if(!built) { if(data != null) { if(data instanceof JedisDataException) throw new JedisDataException((JedisDataException)data); response = builder.build(data); } data = null; built = true; } return response; } public String toString() { return (new StringBuilder()).append("Response ").append(builder.toString()).toString(); } }