redisTemplate类学习及理解
List<Object> list = masterRedisTemplate.executePipelined((RedisCallback<Long>) connection -> { StringRedisConnection redisConn = (StringRedisConnection) connection; Integer expireTime = XXX; redisConn.expire(XXX); RedisUtil.addSameScoreTail(XXXX); return null; });
redisTemplate简化Redis数据访问代码的Helper类。在给定对象和中的基础二进制数据之间执行自动序列化/反序列化。中心方法是execute,支持实现X接口的Redis访问代码,它提供了RedisConnection处理,使得RedisCallback实现和调用代码都不需要显式关心检索/关闭Redis连接,或处理连接生命周期异常。对于典型的单步动作,有各种方便的方法。一旦配置好,这个类就是线程安全的。这是Redis支持的核心类。
1 public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V>, BeanClassLoaderAware {
接口 RedisAccessor:,该接口指定了一组基本的Redis操作,由RedisTemplate实现。不经常使用,但对于可扩展性和可测试性来说是一个有用的选项(因为它很容易被模仿或存根)。
2 private boolean enableTransactionSupport = false;
true:开启之后则开启事务;3 private boolean exposeConnection = false;
曝光链接@Override
public List<Object> executePipelined(RedisCallback<?> action, @Nullable RedisSerializer<?> resultSerializer) {return execute((RedisCallback<List<Object>>) connection -> {
首先开通连接
connection.openPipeline();标志连接是否关闭 这里有个问题时下面这个true设置是为什么 后续是不是会改为false,要不导致内存泄漏了。 :::在deserialize这个方法里传的closePipline参数可以把关闭连接传递过去。
boolean pipelinedClosed = false;
try {其次处理传来的action的doInRedis方法。 这个doinredis方法就是本文第一个代码块的代码,即当前方法入参传过来的代码块的内容。
Object result = action.doInRedis(connection);
if (result != null) {
throw new InvalidDataAccessApiUsageException(
"Callback cannot return a non-null value as it gets overwritten by the pipeline");
}
List<Object> closePipeline = connection.closePipeline();
pipelinedClosed = true;最后调用deserializeMixedResults,把返回结果带入到execute去继续执行。 这个是一个反序列化相关的方法。
return deserializeMixedResults(closePipeline, resultSerializer, hashKeySerializer, hashValueSerializer);
} finally {
if (!pipelinedClosed) {
connection.closePipeline();
}
}
});
}
StringRedisConnection redisConn = (StringRedisConnection) connection; 在调用executePipelined前,可以用来操作数据。
这个execute是executePipelined处理的具体实现。
@Nullable public <T> T execute(RedisCallback<T> action, boolean exposeConnection, boolean pipeline) { Assert.isTrue(initialized, "template not initialized; call afterPropertiesSet() before using it"); Assert.notNull(action, "Callback object must not be null"); RedisConnectionFactory factory = getRequiredConnectionFactory(); RedisConnection conn = null; try { if (enableTransactionSupport) { // only bind resources in case of potential transaction synchronization conn = RedisConnectionUtils.bindConnection(factory, enableTransactionSupport); } else { conn = RedisConnectionUtils.getConnection(factory); } boolean existingConnection = TransactionSynchronizationManager.hasResource(factory); RedisConnection connToUse = preProcessConnection(conn, existingConnection); boolean pipelineStatus = connToUse.isPipelined(); if (pipeline && !pipelineStatus) { connToUse.openPipeline(); } RedisConnection connToExpose = (exposeConnection ? connToUse : createRedisConnectionProxy(connToUse)); T result = action.doInRedis(connToExpose);
具体执行的也是本文最上面的代码块里的方法。
// close pipeline if (pipeline && !pipelineStatus) { connToUse.closePipeline(); } // TODO: any other connection processing? return postProcessResult(result, connToUse, existingConnection); } finally { RedisConnectionUtils.releaseConnection(conn, factory); } }
redisTemplate其他方法
delete
@Override public Boolean delete(K key) { key转成序列化的 byte[] rawKey = rawKey(key); 调用execute方法 Long result = execute(connection -> connection.del(rawKey), true); 判断返回值 return result != null && result.intValue() == 1; }
这个execute也是调用的上面的execute方法,获取到连接之后,执行代码块里的del命令。
expire
加失效时间
@Override public Boolean expire(K key, final long timeout, final TimeUnit unit) { 序列化 byte[] rawKey = rawKey(key);
计算超时时间 long rawTimeout = TimeoutUtils.toMillis(timeout, unit); return execute(connection -> { try {
调用 return connection.pExpire(rawKey, rawTimeout); } catch (Exception e) { // Driver may not support pExpire or we may be running on Redis 2.4 return connection.expire(rawKey, TimeoutUtils.toSeconds(timeout, unit)); } }, true); }
计算好了之后 同样也是通过execute方法,获取连接后执行。
opsForHash
RedisTemplate.opsForHash().put/get/delete等等
HashOperations
@Override public <HK, HV> HashOperations<K, HK, HV> opsForHash() { return new DefaultHashOperations<>(this); } 这个方法实现了hashOperations接口 class DefaultHashOperations<K, HK, HV> extends AbstractOperations<K, Object> implements HashOperations<K, HK, HV> { @SuppressWarnings("unchecked") DefaultHashOperations(RedisTemplate<K, ?> template) { super((RedisTemplate<K, Object>) template); } }
@Override public void put(K key, HK hashKey, HV value) { byte[] rawKey = rawKey(key); byte[] rawHashKey = rawHashKey(hashKey); byte[] rawHashValue = rawHashValue(value); execute(connection -> {
这里通过execute方法,把这个代码块执行。具体的参数是key ,hashkey,value 的三个序列化之后的参数。 connection.hSet(rawKey, rawHashKey, rawHashValue); return null; }, true); }
OpsForSet()
RedisTemplate.opsForSet().add(key, value); public Long add(K key, V... values) { 序列化 byte[] rawKey = rawKey(key);
values是多组二进制 byte[][] rawValues = rawValues((Object[]) values);
return execute(connection -> connection.sAdd(rawKey, rawValues), true); }
大致就是相关的用法,不通的数据结构 ,有自己特有的Operations方法,可以具体查看。