sin*_*ohn 5 java spring redis spring-data-redis
我正在关注RetwisJ教程,可从此处获得。在这种情况下,我认为Redis事务没有实现。例如,在以下函数中,如果在两者之间发生某些异常,则数据将处于不一致状态。我想知道如何在Spring Data Redis中将以下功能作为单个事务实现:
public String addUser(String name, String password) {
String uid = String.valueOf(userIdCounter.incrementAndGet());
// save user as hash
// uid -> user
BoundHashOperations<String, String, String> userOps = template.boundHashOps(KeyUtils.uid(uid));
userOps.put("name", name);
userOps.put("pass", password);
valueOps.set(KeyUtils.user(name), uid);
users.addFirst(name);
return addAuth(name);
}
Run Code Online (Sandbox Code Playgroud)
在这里userIdCounter,valueOps并users在构造函数初始化。我在文档(第4.8节)中遇到了这个问题,但是我无法弄清楚如何将该函数适合在函数外部初始化了一些变量的功能(请不要告诉我必须在每个函数中初始化这些变量)。我需要交易的所有功能!)。
PS:另外@Transaction,Spring Data Redis 是否有任何注释或事务管理器可用?
更新:我尝试使用MULTI,EXEC。我编写的代码是用于另一个项目的,但是将其应用于此问题时,它将如下所示:
public String addMyUser(String name, String password) {
String uid = String.valueOf(userIdCounter.incrementAndGet());
template.execute(new SessionCallback<Object>() {
@Override
public <K, V> Object execute(RedisOperations<K, V> operations)
throws DataAccessException {
operations.multi();
getUserOps(operations, KeyUtils.uid(uid)).put("name", name);
getUserOps(operations, KeyUtils.uid(uid)).put("pass", password);
getValueOps(operations).set(KeyUtils.user(name), uid);
getUserList(operations, KeyUtils.users()).leftPush(name);
operations.exec();
return null;
}
});
return addAuth(name);
}
private ValueOperations<String, String> getValueOps(RedisOperations operations) {
return operations.opsForValue();
}
private BoundHashOperations<String, String, String> getUserOps(RedisOperations operations, String key) {
return operations.boundHashOps(key);
}
private BoundListOperations<String, String> getUserList(RedisOperations operations, String key) {
return operations.boundListOps(key);
}
Run Code Online (Sandbox Code Playgroud)
请告诉我使用这种方式是否MULTI,EXEC建议还是不要。
小智 5
默认情况下,RedisTemplate 不参与托管 Spring 事务。如果您希望 RedisTemplate 在使用 @Transactional 或 TransactionTemplate 时使用 Redis 事务,则需要通过设置 setEnableTransactionSupport(true) 显式启用每个 RedisTemplate 的事务支持。启用事务支持会将 RedisConnection 绑定到 ThreadLocal 支持的当前事务。如果事务完成且没有错误,Redis 事务将通过 EXEC 提交,否则通过 DISCARD 回滚。Redis 事务是面向批量的。在正在进行的事务期间发出的命令会排队,并且仅在提交事务时应用。
Spring Data Redis 区分正在进行的事务中的只读命令和写入命令。只读命令(例如 KEYS)通过管道传输到新的(非线程绑定)RedisConnection 以允许读取。写入命令由 RedisTemplate 排队并在提交时应用。
https://docs.spring.io/spring-data/data-redis/docs/current/reference/html/#tx.spring
在 SD Redis 1.2 之前,您必须使用TransactionSynchronizationManager自行处理事务
上面的代码片段可能看起来像这样:
public String addUser(String name, String password) {
String uid = String.valueOf(userIdCounter.incrementAndGet());
// start the transaction
template.multi();
// register synchronisation
if(TransactionSynchronisationManager.isActualTransactionActive()) {
TransactionSynchronisationManager.registerSynchronisation(new TransactionSynchronizationAdapter()) {
@Override
public void afterCompletion(int status) {
switch(status) {
case STATUS_COMMITTED : template.exec(); break;
case STATUS_ROLLED_BACK : template.discard(); break;
default : template.discard();
}
}
}
}
BoundHashOperations<String, String, String> userOps = template.boundHashOps(KeyUtils.uid(uid));
userOps.put("name", name);
userOps.put("pass", password);
valueOps.set(KeyUtils.user(name), uid);
users.addFirst(name);
return addAuth(name);
}
Run Code Online (Sandbox Code Playgroud)
请注意,一旦进入多模式,读取操作也将成为事务的一部分,这意味着您可能无法从 Redis 服务器读取数据。该设置可能与上述设置不同,因为您可能需要额外调用WATCH. 此外,您还必须处理多个回调,不要发送MULTI和/或EXEC多次。
即将推出的 Spring Data Redis 1.3 版本将支持 Spring 管理的事务,以照顾MULTi|EXEC|DISCARD事务同步处于活动状态时,可以处理并允许读取操作(在现有的键上)。您已经可以尝试一下 BUILD-SNAPSHOT 并通过设置将其打开template.setEnableTransactionSupport(true)。
| 归档时间: |
|
| 查看次数: |
7056 次 |
| 最近记录: |