【问题标题】:Spring Data support for Redis BRPOPLPUSHSpring Data 对 Redis BRPOPLPUSH 的支持
【发布时间】:2017-08-06 10:12:16
【问题描述】:

我正在使用 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)



问题_0:这是唯一的选择吗?为什么上面两个api都没有?

Answer_0:不,只要在boundListOpsopsForList 中用left/rightPop(timeout, unit) 提及时间单位,它就会阻塞调用。 0秒的时间单位永远阻塞。

问题_1:为什么会有这么多变种..?或者可能何时使用boundListOpsopsForListgetConnection

Partial_Answer_1:看起来如果多个操作要作用于单个键然后boundListOps,因为它绑定到单个键,并且在重复动作中无需提及,其中如opsForList,每个操作键都必须提到。

来自boundListOps的文档:

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

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

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

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

从代码中boundListOps 本质上是使用 opsForList,它的所有动作都是用 finally 执行的,如下所示,带有释放连接,因此被问到。

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);
        }

问题_3:为什么getRedisTemplate().boundListOps("key").rightPush(new HashMap()); 接受Map 而不是像String/Object 这样的值,虽然"key" 已经被提及...?

Answer_3:这是我的问题,我已经这样声明了。

public RedisTemplate<String, Map<String, Object>> getRedisTemplate() {
        return redisTemplate;
}

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

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();
    }
}

问题_4:为什么getConnection().bRPopLPush 接受srcKey, dstKey 作为byte[] 而不是String ..?

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

【问题讨论】:

    标签: redis jedis spring-data-redis


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        猜你喜欢
        • 2017-05-06
        • 2018-06-20
        • 2016-07-05
        • 2021-03-09
        • 2015-06-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-27
        相关资源
        最近更新 更多