一、什么是事务
事务(Transaction)是一种并发控制单元。在关系型数据库中,事务是一组操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单元。但是redis的事务,稍有不同。
二、为什么需要使用事务
以支付场景为例,A向B支付100元,需要在A的账户中扣去100元,在B的账户中增加100元。这两个操作如果其中一个操作成功,另一个操作失败,就会导致问题。比如A付了钱B没有收到,或者A没付钱B收到了。我们可以使用事务将这两个操作变成一个原子性操作,要么一起成功,要么都不成功
三、事务使用的基本流程
- 普通事务使用
- 开启事务
- 执行事务操作,提交事务
- 事务操作出现异常,回滚事务
Java示例代码如下:
// 开启事务
begin();
try {
// 执行业务
doSomeThing();
// 提交事务
commit();
} catch(Exception e) {
// 回滚事务
rollback();
}
- redis事务使用
- 开始事务 (multi)
- 命令入队
- 执行事务/放弃事务
示例如下:
// 开启事务
> multi
OK
// 命令 入队
> set key val
QUEUED
> set key1 val1
QUEUED
> get key
QUEUED
// 执行事务/取消事务
> exec(discard)
OK
执行流程如下:
差异
redis中的事务操作有三种错误,分别是运行时错误,入队时错误(不终止事务),入队时错误(终止事务)。redis中的事务不支持回滚!!!
官方文档解释如下:
If you have a relational databases background, the fact that Redis commands can fail during a transaction, but still Redis will >execute the rest of the transaction instead of rolling back, may look odd to you.
However there are good opinions for this behavior:
Redis commands can fail only if called with a wrong syntax (and the problem is not detectable during the command queueing), >or against keys holding the wrong data type: this means that in practical terms a failing command is the result of a >programming errors, and a kind of error that is very likely to be detected during development, and not in production.
Redis is internally simplified and faster because it does not need the ability to roll back.
An argument against Redis point of view is that bugs happen, however it should be noted that in general the roll back does not >save you from programming errors. For instance if a query increments a key by 2 instead of 1, or increments the wrong key, >there is no way for a rollback mechanism to help. Given that no one can save the programmer from his or her errors, and that >the kind of errors required for a Redis command to fail are unlikely to enter in production, we selected the simpler and faster >approach of not supporting roll backs on errors.
说redis的命令在事务中可以失败,但是redis仍然会在失败后执行后面的命令而不是回滚。
redis的命令可能会发生语法错误,或者keys持有了错误的数据类型,但是这种错误在命令入队时不会被发现,这意味着错误是由于编程错误导致的,这是一种在开发环境中可以发现的错误而不该出现在生产环境。
redis追求简单快速的设计理念,所以它不需要回滚的能力
bug总会发生,需要明白的是回滚并不会纠正你的编码错误。比如说一个请求需要将某个key值增加2而不是1,或者增加到了错误的key上,这些错误使用回滚机制并没有帮助。程序员自己的错误是无法拯救的,那些会导致redis命令失败的错误不应该出现在生产环境,我们选择了一个简单快速的方案,在发生错误时不去回滚。
根据官方的解释,可以总结出redis的事务只能保证按顺序执行一组操作,但是不支持要么一起成功,要么一起失败。