Spring Data支持Redis BRPOPLPUSH

时间:2017-08-06 10:12:16

标签: redis jedis spring-data-redis

我正在使用Jedis通过Spring Data访问Redis。

<bean
    id="jedisPoolConfig"
    class="redis.clients.jedis.JedisPoolConfig"
    p:maxTotal="100"
    p:maxIdle="10"
    p:maxWaitMillis="5000"
/> 

<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
    p:host-name="${redis.server.host}" p:port="${redis.server.port}"
    p:password="${redis.server.password}" 
    p:use-pool="${redis.server.usepool}" 
    p:pool-config-ref="jedisPoolConfig"/>

<bean id="genericJackson2JsonRedisSerializer" class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>

<bean id="stringSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>       


<!-- redis template definition -->  
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"      p:connection-factory-ref="jedisConnectionFactory">      <property name="keySerializer" ref="stringSerializer"/>
        <property name="hashKeySerializer" ref="stringSerializer"/>
        <property name="hashValueSerializer" ref="genericJackson2JsonRedisSerializer"/>
</bean>     

<bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate"      p:connection-factory-ref="jedisConnectionFactory" />

想要执行BRPOPLPUSH,我在

下看不到这个选项
   OPTION_1  -> getRedisTemplate().boundListOps("Key").*

   OPTION_2 -> getRedisTemplate().opsForList().rightPopAndLeftPush("sourceKey", "destinationKey")  ---> No blocking ? 

相反,它可以在,

   OPTION_3 -> getRedisTemplate().getConnectionFactory().getConnection().bRPopLPush(timeout, srcKey, dstKey)



Question_0 :这是唯一的选择吗?为什么它不能用于上述两个api?

Answer_0 :不,每当left/rightPop(timeout, unit) boundListOps opsForList提及时间单位时,boundListOps就会阻止通话。 timeunit用0秒阻止永远。

Question_1 :为什么有这么多变种..?或者可能何时使用opsForListgetConnectiongetConnectionFactory().getConnection()

Partial_Answer_1 :看起来如果要对单个键执行多个操作,那么bindListOps,因为它绑定到该单个键,并且在重复操作中无需提及,其中opsForList,必须提到每个操作键。

来自boundListOps的文档:

  

返回对绑定到给定的列表值执行的操作   键。

请注意,boundListOps仍然通过将注册密钥传递给它来固有地使用opsForList。

好的,我应该何时直接使用getConnectionFactory().getConnection()

问题_2 :如果我使用finally(){},我是否需要在blocking RPopLPush下关闭()此连接? (因为这是目前正在boundListOps支持的那个)。

从代码RedisTemplate.java public <T> T execute(RedisCallback<T> action, boolean exposeConnection, boolean pipeline) { RedisConnectionFactory factory = getConnectionFactory(); RedisConnection conn = null; try { conn = RedisConnectionUtils.getConnection(factory); ... ... // TODO: any other connection processing? return postProcessResult(result, connToUse, existingConnection); } finally { RedisConnectionUtils.releaseConnection(conn, factory); } 本身就是使用opsForList,并且它的所有动作最终都像下面那样执行释放连接,因此被问到。

getRedisTemplate().boundListOps("key").rightPush(new HashMap());

问题3 :为什么Map接受String/Object而不是"key"之类的值虽然已经提到过public RedisTemplate<String, Map<String, Object>> getRedisTemplate() { return redisTemplate; } ...?

Answer_3 :这是我的问题,我已经宣布了这一点。

public BoundListOperations<K, V> boundListOps(K key) {
    return new DefaultBoundListOperations<K, V>(key, this);
}

class DefaultBoundListOperations<K, V> extends DefaultBoundKeyOperations<K> implements BoundListOperations<K, V> {

    public DefaultBoundListOperations(K key, RedisOperations<K, V> operations) {
        super(key, operations); //RedisOperations<K, V> is converted to BoundListOperations<K, V> here
        this.ops = operations.opsForList();
    }
}

同时传递相同的RedisTemplate对象,同时获取DefaultBoundListOperations,其中V是从RedisTemplate引用的。

getConnection().bRPopLPush

Question_4 :为什么srcKey, dstKey接受byte[]作为String而不是{{1}} ..?

很抱歉很多问题,所有提出的都是因为我在spring数据或教程中找不到合适的java doc来解释用法。

2 个答案:

答案 0 :(得分:0)

关于问题4:首先,重要的是要注意Redis键和值can be any binary。 Spring数据模板将其抽象出来,让开发人员处理Java对象而不是字节数组。请参阅spring-data reference

中的以下引用
  

...该模板为Redis交互提供了高级抽象。虽然RedisConnection提供了接受和返回二进制值(字节数组)的低级方法,但模板负责序列化和连接管理,使用户无需处理这些细节。

似乎在使用RedisConnection时,Spring不知道您的键或值是什么类型,并且它不会将对象(例如String)转换为二进制Redis。因此,您需要将原始二进制文件传递给Redis。

答案 1 :(得分:0)

首先,致电RedisTemplate.opsForList()以获得ListOperations。 然后,使用ListOperations.rightPopAndLeftPush(K sourceKey, K destinationKey, long timeout, TimeUnit unit)进行BRPOPLPUSH。