Spring and Redis integration details 2

Detailed explanation of Jedis getting Redis connection: http://donald-draper.iteye.com/blog/2347121
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();
    }
}

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326817906&siteId=291194637