我正在使用带有Redis的Spring Boot 2.0.3(通过stringRedisTemplate)。我写了一个简单的速率限制器来限制用户对某些资源的访问。我想自动发送一个incr和一个expire来使redis失效,这样我可以确定没有expire不会创建任何键。我不想在全局范围内启用Redis事务,而只是在这种情况下。为此,我编写了以下内容:
SessionCallback<List<Object>> sessionCallback = new SessionCallback<List<Object>>() {
@SuppressWarnings("unchecked")
@Override
public <K, V> List<Object> execute(RedisOperations<K, V> operations) throws DataAccessException {
operations.multi();
operations.opsForValue().increment((K) key, 1);
operations.expire((K) key, rateIntervalTime.getTimeAmount(), rateIntervalTime.getTimeUnit());
return operations.exec();
}
};
执行此操作会引发以下错误:org.springframework.data.redis.RedisSystemException: Unknown redis exception; nested exception is java.lang.IllegalArgumentException: Incorrect number of transaction results. Expected: 2 Actual: 1
看起来过期在这里触发了错误。
我现在尝试了一些不同的操作-用RedisCallback
而不是SessionCallback
。这行得通!
RedisCallback<List<Object>> redisCallback = new RedisCallback<List<Object>>() {
@Override
public List<Object> doInRedis(RedisConnection connection) throws DataAccessException {
connection.multi();
connection.incr(key.getBytes());
connection.expire(key.getBytes(),
rateIntervalTime.getTimeUnit().toSeconds(rateIntervalTime.getTimeAmount()));
return connection.exec();
}
};
所以现在我有以下问题(对他们中的任何一个的回答都很感激):
RedisCallback
一起使用而不与SessionCallback
一起使用?doInRedis
和execute
方法中的所有键都相同,是否可以将这些事务与Redis群集一起使用?executePipelined
而不是execute
执行此命令时,似乎仍然没有命令作为一条批量消息到达。我在multi
之后设置了一个断点,并且在执行其他命令(monitor
+ incr
之前,用expire
观看redis时仍然可以看到该命令到达注意:当我使用Spring Boot 2.0.3时,我正在使用Lettuce Redis驱动程序。但是切换到Jedis会得到相同的结果。