Redis中是支持事务的,他的事务主要目的是保证多个命令执行的原子性,即要在一个原子操作中执行,不会被打断。
需要注意的是,Redis的事务是不支持回滚的。从 Redis 2.6.5 开始,服务器将会在累积命令的过程中检测到错误。然后,在执行 EXEC 期间会拒绝执行事务,并返回一个错误,同时丢弃该事务。如果事务执行过程中发生错误,Redis会继续执行剩余的命令而不是回滚整个事务。
Errors happening after EXEC instead are not handled in a special way: all the other commands will be executed even if some command fails during the transaction.
https://redis.io/docs/interact/transactions/#errors-inside-a-transaction
更多原子性的解释参考:
Redis事务相关的命令主要有以下几个:
前面我们提到过,从 Redis 2.6.5 开始,服务器将会在累积命令的过程中检测到错误。但是后面又说事务执行时也会有错误。这里是不是矛盾了?
其实并不矛盾。
Redis错误有两种情况,一种是在命令排队的过程就就检测到的错误,比如语法错误,比如内存不够了,等等。在这种错误,会在调用 EXEC 后,命令可能会直接失败。
还有一种错误,是在调用 EXEC 后,命令执行过程中出现的错误,最常见的就是操作类型不一致,比如对字符串进行列表相关的操作。这种就是在执行过程中才会出现的。
而后面这种错误,Redis认为是不应该出现的。所以需要在开发阶段就避免,这也是他没有提供回滚的一个重要原因。
下面是一个使用Jedis客户端,借助事务实现电商下单的例子:
Jedis jedis = new Jedis("localhost", 6379);
// 开启事务 : MULTI
Transaction tx = jedis.multi();
// 扣减库存
tx.decrBy("item:10001:stock", 1);
// 计算商品总价
tx.mul(100, 2);
// 下单记录
tx.rpush("orders", "user:10001,item:10001,amount:2,total:200");
// 执行事务 : EXEC
List<Object> result = tx.exec();
// 检查事务执行结果
if (result == null) {
System.out.println("事务执行失败!");
} else {
System.out.println("事务执行成功,订单已提交!");
}