[REDIS] 트랜잭션이 풀 다음 블록에 연결을 반환하지 봄 RedisConnectionFactory 때 소진
REDIS트랜잭션이 풀 다음 블록에 연결을 반환하지 봄 RedisConnectionFactory 때 소진
연결 풀과 연결 팩토리를 작성하기위한 내 구성. 나는 연결 풀을해야합니까. 이 코드의 대부분은 내가 특정 이유로 비활성화 봄의 RedisAutoConfiguration에서 복사됩니다.
@Configuration
@EnableConfigurationProperties(RedisProperties.class)
public class JedisConfiguration implements RedisConfiguration {
@Bean
@Scope("prototype")
@Override
public RedisConnectionFactory connectionFactory(RedisProperties redisProperties) {
return createFactory(redisProperties);
}
private static JedisConnectionFactory applyProperties(RedisProperties properties, JedisConnectionFactory factory) {
factory.setHostName(properties.getHost());
factory.setPort(properties.getPort());
factory.setDatabase(properties.getDatabase());
return factory;
}
private static JedisPoolConfig jedisPoolConfig(RedisProperties properties) {
return Optional.ofNullable(properties.getPool())
.map(props -> {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(props.getMaxActive());
config.setMaxIdle(props.getMaxIdle());
config.setMinIdle(props.getMinIdle());
config.setMaxWaitMillis(props.getMaxWait());
return config;
})
.orElseGet(JedisPoolConfig::new);
}
public static JedisConnectionFactory createFactory(RedisProperties properties) {
return applyProperties(properties, new JedisConnectionFactory(jedisPoolConfig(properties)));
}
}
내가 문자열 키가 "A"는 "B는"해시 "C"매핑 클래스 A, 각각 B와 C에서 직렬화 된 JSON 문자열 해시 키와 해시 값으로 매핑합니다.
>은 :: toString - - B와 C에 대한> JSON (A)와 같은 즉 "A"입니다
@Component
public final class UseCase implements InitializingBean {
private static final String A_KEY = "A";
private static final String B_KEY = "B";
private static final String C_KEY = "C";
private final RedisConnectionFactory factory;
private final ObjectMapper objectMapper;
private HashOperations<String, String, A> aMap;
private HashOperations<String, String, B> bMap;
private HashOperations<String, String, C> cMap;
private RedisTemplate<String, ?> template;
private UseCase(RedisConnectionFactory factory, ObjectMapper objectMapper) {
this.factory = factory;
this.objectMapper = objectMapper;
}
private <T> RedisTemplate<String, ?> hashMap(Class<T> vClass) {
RedisTemplate<String, ?> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(stringSerializer());
redisTemplate.setHashKeySerializer(stringSerializer());
redisTemplate.setHashValueSerializer(jacksonSerializer(vClass));
return configure(redisTemplate);
}
private <K, V> RedisTemplate<K, V> configure(RedisTemplate<K, V> redisTemplate) {
redisTemplate.setConnectionFactory(factory);
redisTemplate.setEnableTransactionSupport(true);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
private <T> RedisSerializer<T> jacksonSerializer(Class<T> clazz) {
Jackson2JsonRedisSerializer<T> serializer = new Jackson2JsonRedisSerializer<>(clazz);
serializer.setObjectMapper(objectMapper);
return serializer;
}
private RedisSerializer<String> stringSerializer() {
return new StringRedisSerializer();
}
@Override
public void afterPropertiesSet() throws Exception {
template = hashMap(String.class);
aMap = hashMap(A.class).opsForHash();
bMap = hashMap(B.class).opsForHash();
cMap = hashMap(C.class).opsForHash();
}
void put(A a, B b, C c) {
template.multi();
aMap.put(A_KEY, a.toString(), a);
bMap.put(B_KEY, b.toString(), b);
cMap.put(C_KEY, c.toString(), c);
template.exec();
}
A getA(String aKey) {
return aMap.get(A_KEY, aKey);
}
}
그러나 나는 내가 조금 회의적하지만 내 문제는 지난 2로, 즉 하나 개의 작품을 입증하는 시험이있다. 디버깅 후, 나는 연결이 중 수술 후 풀에 반환되지 않으며이 소진 때 따라서 수영장이 차단됩니다 것을 관찰했다.
반환 시도하지만, 두 가지 아래에 실패하기 때문에 연결에 호출되지 않습니다. RedisConnectionUtils에서 촬영
// release transactional/read-only and non-transactional/non-bound connections.
// transactional connections for read-only transactions get no synchronizer registered
if (isConnectionTransactional(conn, factory)
&& TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
unbindConnection(factory);
} else if (!isConnectionTransactional(conn, factory)) {
if (log.isDebugEnabled()) {
log.debug("Closing Redis Connection");
}
conn.close();
}
해결법
-
==============================
1.나는 문제가 간부 인 ()를 호출하는 것은이 풀에 반환 될 수 있도록 실제로 연결을 완료하는 템플릿을 말하지 않는다는 것입니다 생각합니다.
나는 문제가 간부 인 ()를 호출하는 것은이 풀에 반환 될 수 있도록 실제로 연결을 완료하는 템플릿을 말하지 않는다는 것입니다 생각합니다.
워드 프로세서에 따르면 당신은 SessionCallback에 코드를 포장하고 RedisTemplate.execute 그것을 실행하는 거 야 (SessionCallback
콜백) 콜백이 실행 된 후 풀에 연결을 반환하는. 이 같이 :
template.execute(new SessionCallback<List<Object>>() { public List<Object> execute(RedisOperations operations) throws DataAccessException { operations.multi(); aMap.put(A_KEY, a.toString(), a); bMap.put(B_KEY, b.toString(), b); cMap.put(C_KEY, c.toString(), c); return operations.exec(); } });
봄 데이터 레디 스도 @Transactional에 대한 지원이있는 당신을 위해 자동으로 바인드 / 언 바인드 연결되지만, 가로 챌 수 있습니다 (즉, 그것이 마지막이 될 수 없습니다) 및 트랜잭션이있는 경우에만 시작됩니다 빈의 메소드를 구현하도록 요구 빈 외부에서 실행되는 (즉, 동일하지 클래스 또는 하위 / 상위 클래스에서 다른 방법으로).
이미 redisTemplate.setEnableTransactionSupport (사실)와 템플릿에 트랜잭션 지원을 가능하게하고, 그래서 당신은 갈 수 있어야한다 :
@Transactional public void put(A a, B b, C c) { aMap.put(A_KEY, a.toString(), a); bMap.put(B_KEY, b.toString(), b); cMap.put(C_KEY, c.toString(), c); }
from https://stackoverflow.com/questions/46238811/spring-redisconnectionfactory-with-transaction-not-returning-connection-to-pool by cc-by-sa and MIT license
'REDIS' 카테고리의 다른 글
[REDIS] 레디 스는 게시 / 구독 : 채널이 현재 가입하고있는 무슨 참조 (0) | 2020.01.14 |
---|---|
[REDIS] 어떻게 Node.js를 파이프 라인에 레디 스 하는가? (0) | 2020.01.14 |
[REDIS] 레디 스에 쿼리? (0) | 2020.01.13 |
[REDIS] 어떻게 노드를 사용하여 레디 스에서 이진 객체를 저장? (0) | 2020.01.13 |
[REDIS] Resque와 레일와 레디 스 : ERR 명령이 허용되지 않는 경우에 사용되는 메모리> 'maxmemory' (0) | 2020.01.13 |