SessionCallback
Redis
пройти черезmulti
, exec
, илиdiscard
команды для обеспечения поддержки транзакций, эти операцииRedisTemplate
中同样是可用的。 но,RedisTemplate
дефолтиспользоватьRedisCallBackинтерфейс, нет гарантии, что одно и то же соединение будет использоваться для выполнения всех операций в одной и той же транзакции (когдаTransaction
это недействительно).
Но опять же,Spring Data Redis
при условииSessionCallbackинтерфейс, чтобы убедиться, что同一连接
Используется при выполнении множества операций, таких как «необходимость использованияRedis事务
время». Мы видим:
public <T> T execute(SessionCallback<T> session) {
Assert.isTrue(initialized, "template not initialized; call afterPropertiesSet() before using it");
Assert.notNull(session, "Callback object must not be null");
RedisConnectionFactory factory = getConnectionFactory();
// bind connection
RedisConnectionUtils.bindConnection(factory, enableTransactionSupport);//第8行
try {
return session.execute(this);
} finally {
RedisConnectionUtils.unbindConnection(factory);
}
}
RedisTemplate.execute(SessionCallback<T> session)
метод第8行
уже сделано连接绑定
;
Он используется следующим образом:
//execute a transaction
List<Object> txResults = redisTemplate.execute(new SessionCallback<List<Object>>() {
public List<Object> execute(RedisOperations operations) throws DataAccessException {
operations.multi();
operations.opsForSet().add("key", "value1");
// This will contain the results of all ops in the transaction
return operations.exec();
}
});
System.out.println("Number of items added to set: " + txResults.get(0));
Перед возвратом RedisTemplate будет использовать сериализаторы своего значения, хеш-ключа и хеш-значения для десериализации всех результатов exec. Дополнительный метод exec, который позволяет передавать пользовательские сериализаторы для результатов транзакций.
@Транзакционная поддержка
Выше мы можем видеть, вы можетеSessionCallback绑定连接
, и осознатьmulti
, exec
,илиdiscard
, тем самым поддерживаяRedis事务
, но это кажется сложным иRedis操作(opsXXX.X)
Место выполнения также становится ограничительным (хотя и не влияет на функциональность).
Тем не мение,Spring
Далее мы можем сделать это еще проще, всего два шага:
- за
method
Добавить аннотацию **@TransactionalилиКонфигурация XML** (), зарегистрироватьсяточка транзакции. эквивалентно вызовуTransactionSynchronizationManager.setActualTransactionActive(true); - пройти черезsetEnableTransactionSupport(true)Явно включено
RedisTemplate
пример事务支持
(отключен по умолчанию)
/** Sample Configuration **/
@Configuration
public class RedisTxContextConfiguration {
@Bean
public StringRedisTemplate redisTemplate() {
StringRedisTemplate template = new StringRedisTemplate(redisConnectionFactory());
// explicitly enable transaction support
template.setEnableTransactionSupport(true);
return template;
}
}
экземпляр redisTemplateвызов по умолчаниюexecute(RedisCallback action)Метод следующим образом:
public <T> T execute(RedisCallback<T> action, boolean exposeConnection, boolean pipeline){
/**
* 变量声明等操作……
*/
try {
if (enableTransactionSupport) {
// only bind resources in case of potential transaction synchronization
conn = RedisConnectionUtils.bindConnection(factory, enableTransactionSupport);
} else {
conn = RedisConnectionUtils.getConnection(factory);
}
/**
* 其他操作……
*/
}
public static RedisConnection bindConnection(RedisConnectionFactory factory,
boolean enableTransactionSupport) {
/**
* 不用管……
*/
RedisConnection conn = factory.getConnection();
RedisConnection connectionToBind = conn;
//redisTemplate开启事务支持,同时transactionManager非只读的实际事务被激活
if (enableTransactionSupport && isActualNonReadonlyTransactionActive()) {
connectionToBind = createConnectionProxy(conn, factory);
}
/**
* 不用管……
*/
return conn;
}
можно увидеть,enableTransactionSupport = trueподскажет текущийThread
попытаться связатьRedisConnection
, только если такжеisActualNonReadonlyTransactionActive = true, соединение будет успешно установлено.
привязка соединенияУспешный и будет вызватьMULTI
. однаждыMULTI
называется:
- Текущий
RedisConnection
выстроится в очередьwrite操作
; - все
readonly操作
,НапримерKEYS
Он будет распространен на новый (неThread
граница)RedisConnection
; - Заказ
EXEC
илиDISCARD
будет переданоSpringAOPиздинамический прокси-объектзвонить: - если
事务构建
нет процесса异常抛出
(дефолтRuntimeException
и его подклассы), тоEXEC
Вызывается для выполнения очереди команд; - в противном случае
DISCARD
, Четкая командная очередь.
После включения поддержки транзакций:
/** Usage Constrainsts **/
// executed on thread bound connection
template.opsForValue().set("foo", "bar");
// read operation executed on a free (not tx-aware)
connection template.keys("*");
// returns null as values set within transaction are not visible
template.opsForValue().get("foo");
Пример кода вышеофициальный сайт весныданный,ТретийочевидноWATCH
команда乐观锁
Результаты после. Однако, по крайней мере, в моем будущем я использовалspring-data-redis-1.8.10.RELEASE.jarсередина,
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.8.10.RELEASE</version>
</dependency>
WATCH
команда не используется,Протест第三种
Эффекта не существует (вы можете попробовать его в соответствии со своей версией зависимостей), код показан здесь.
- org.springframework.data.redis.core.RedisConnectionUtils.potentiallyRegisterTransactionSynchronisation
private static void potentiallyRegisterTransactionSynchronisation(RedisConnectionHolder connHolder,
final RedisConnectionFactory factory) {
if (isActualNonReadonlyTransactionActive()) {
if (!connHolder.isTransactionSyncronisationActive()) {
connHolder.setTransactionSyncronisationActive(true);
RedisConnection conn = connHolder.getConnection();
conn.multi();//在此之前conn.watch()未被调用
TransactionSynchronizationManager.registerSynchronization(new RedisTransactionSynchronizer(connHolder, conn,
factory));
}
}
}
утверждение两个
Экземпляр RedisTemplate
дваRedisTemplate
пример?
-
служба поддержкиСделка:
commands
или统一执行
, или都被清除
, для поддержания целостности данных; -
не поддерживаетсядела,
command
выполнить немедленно, вернуть немедленно执行结果
и больше高效
;
/** Sample Configuration **/
@Configuration
public class RedisTxContextConfiguration {
@Bean
public StringRedisTemplate redisTransactionTemplate() {
StringRedisTemplate template = new StringRedisTemplate(redisConnectionFactory());
// explicitly enable transaction support
template.setEnableTransactionSupport(true);
return template;
}
@Bean
public StringRedisTemplate redisTemplate() {
StringRedisTemplate template = new StringRedisTemplate(redisConnectionFactory());
return template;
}
}