java – 如何以干净的方式在Spring Data Redis中实现事务?
作者:互联网
我正在关注RetwisJ教程here.在此我不认为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);
}
这里userIdCounter,valueOps和用户在构造函数中初始化.我在文档中遇到了this(第4.8节),但是我无法弄清楚如何将其纳入此函数中,其中一些变量在函数外部初始化(请不要告诉我必须在每个函数中初始化这些变量)我需要交易的每个功能!).
PS:还有可用于Spring Data Redis的@Transaction注释或事务管理器吗?
更新:我尝试过使用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);
}
请告知是否建议使用MULTI,EXEC这种方式.
解决方法:
在SD Redis 1.2之前,您必须使用TransactionSynchronisationManager自行处理任务
上面的snipplet可能看起来像这样:
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);
}
请注意,一旦处于多个状态,读取操作也将成为事务的一部分,这意味着您可能无法从redis服务器读取数据.
设置可能与上面的设置不同,因为您可能需要另外调用WATCH.此外,您还必须处理多个回调,不要多次发送MULTI和/或EXEC.
即将发布的Spring Data Redis的1.3版本将支持Spring管理事务,以便在事务同步处于活动状态时处理MULTi | EXEC | DISCARD以及允许读取操作(在现有密钥上).你可以通过设置template.setEnableTransactionSupport(true)给BUILD-SNAPSHOT一个旋转并打开它.
标签:java,spring,redis,spring-data-redis 来源: https://codeday.me/bug/20190708/1406211.html