Redis 之事务
为了确保连续多个操作的原子性,一个成熟的数据库通常都会有事务支持,Redis 也同样如此。Redis 的事务使用非常简单,不同于关系数据库,我们无须理解那么多复杂的事务模 型,就可以直接使用。
1. Redis 事务的基本使用
每个事务的操作都有 begin、commit 和 rollback,begin 指示事务的开始,commit 指示 事务的提交,rollback 指示事务的回滚。
Redis 事务的形式也是差不多的,分别是 multi/exec/discard
1. multi:事务的开始
2. exec:事务的执行
3. discard:事务的丢弃
所有的指令在 exec 之前不执行,而是缓存在服务器的一个事务队列中,服务器一旦收到 exec 指令,才开执行整个事务队列,执行完毕后一次性返回所有指令的运行结果。
2. 原子性
事务的原子性指要么事务全部成功,要么全部失败,Redis其实是不支持原子性的:
> multi
OK
> set redis abc
QUEUED
> incr redis
QUEUED
> set book book
QUEUED
> exec
1) OK
2) (error) ERR value is not an integer or out of range
3) OK
> get redis
"abc"
> get book
"book"
>
可以看到上述操作中,事务执行到中间失败了(字符串是不可以自增的),虽然失败了,但是后面的指令可以执行
由此可以看出:Redis 的事务,是不能算原子性 ,仅仅满足了事务的隔离性,我们可以使用 discard 丢弃队列中的指令。
3. 为什么 Redis 的事务不能支持回滚
1. Redis 命令只会因为错误的语法而失败(并且这些问题不能在入队时发现)﹐或是命令用在了错误类型的键上面:这也就是说﹐从实用性的角度来说﹐失败的命令是由编程错误造成的﹐而这些错误应该在开发的过程中被发现﹐而不应该出现在生产环境中。
2. Redis 处理事务的做法会产生 bug,然而需要注意的是﹐在通常情况下﹐回滚并不能解决编程错误带来的问题,如果你本来想通过 INCR 命令将键的值加上1,却不小心加上了2,又或者对错误类型的键执行了 INCR,回滚是没有办法处理这些情况的
3. 因次 Redis 不需要对回滚进行支持﹐所以 Redis 的内部可以保持简单且快速。