关闭redis开启事务支持

 <bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
    <property name="connectionFactory" ref="jedisConnectionFactory" />
    <!-- 开启事务 -->
    <property name="enableTransactionSupport" value="false"></property>
</bean>

或者

 @Bean
 public StringRedisTemplate redisTransactionTemplate() {
    StringRedisTemplate template = new StringRedisTemplate(redisConnectionFactory());
    template.setEnableTransactionSupport(true);
    return template;
  }

原因分析

org.springframework.data.redis.core.RedisTemplate.java

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 = getConnectionFactory();
	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 {

		if (!enableTransactionSupport) {
			RedisConnectionUtils.releaseConnection(conn, factory);
		}
	}
}

接着调用org.springframework.data.redis.core.RedisConnectionUtils获取redis连接

public static RedisConnection doGetConnection(RedisConnectionFactory factory, boolean allowCreate, boolean bind,
			boolean enableTransactionSupport) {

	Assert.notNull(factory, "No RedisConnectionFactory specified");

	RedisConnectionHolder connHolder = (RedisConnectionHolder) TransactionSynchronizationManager.getResource(factory);

	if (connHolder != null) {
		if (enableTransactionSupport) {
			potentiallyRegisterTransactionSynchronisation(connHolder, factory);
		}
		return connHolder.getConnection();
	}

	if (!allowCreate) {
		throw new IllegalArgumentException("No connection found and allowCreate = false");
	}

	if (log.isDebugEnabled()) {
		log.debug("Opening RedisConnection");
	}

	RedisConnection conn = factory.getConnection();

	if (bind) {

		RedisConnection connectionToBind = conn;
		// 此处判断是否开启了redis事务 && 是否存在spring事务
		if (enableTransactionSupport && isActualNonReadonlyTransactionActive()) {
			connectionToBind = createConnectionProxy(conn, factory);
		}

		connHolder = new RedisConnectionHolder(connectionToBind);

		TransactionSynchronizationManager.bindResource(factory, connHolder);
		// 此处开启redis事务
		if (enableTransactionSupport) {
			potentiallyRegisterTransactionSynchronisation(connHolder, factory);
		}

		return connHolder.getConnection();
	}

	return conn;
}


private static void potentiallyRegisterTransactionSynchronisation(RedisConnectionHolder connHolder,
			final RedisConnectionFactory factory) {

	if (isActualNonReadonlyTransactionActive()) {

		if (!connHolder.isTransactionSyncronisationActive()) {
			connHolder.setTransactionSyncronisationActive(true);

			RedisConnection conn = connHolder.getConnection();
			// 开启redis事务==>该conn所有的执行将返回null
			conn.multi();

			TransactionSynchronizationManager.registerSynchronization(new RedisTransactionSynchronizer(connHolder, conn,
					factory));
		}
	}
}

private static boolean isActualNonReadonlyTransactionActive() {
	return TransactionSynchronizationManager.isActualTransactionActive()
			&& !TransactionSynchronizationManager.isCurrentTransactionReadOnly();
}

参考

  1. Redis之坑:spring-data-redis中的Redis事务