作为一个nosql
数据库,事务是必要功能.但是redis我们是可以理解为它不支持事务操作的,因为它的特征完全不满足我们对事物的正常理解
ps:我不知道是谁一开始提出redis支持事务的,但是我更倾向于这是redis的
多命令
功能
multi
这个命令单词意思已经说明了一切,我只能理解为中文文档一厢情愿了
事务的使用
1. 开启事务
命令:multi
127.0.0.1:6379> multi
OK
执行该命令后,连接会进入事务模式
2.执行操作
可以执行任意的redis数据操作命令,那么执行操作会进入一个待执行队列
127.0.0.1:6379> set name zhangsan
QUEUED
127.0.0.1:6379> set age 34
QUEUED
3.提交事务
命令:exec
提交之后,待执行队列
中的命令将执行
127.0.0.1:6379> exec
1) OK
2) OK
待执行队列清除
清空队列:discard
事务的具体情况处理
Redis事务的特点
1.没有隔离级别的概念
开启事务之后的操作全部是在待执行队列
中缓存,并没有真正执行,也就不存在事务内部的查询要看到事务即将的更新,事务外部也不知道
2.不保证原子性
Redis对单条命令是保证原子性(比如批量msetnx
命令),但是如果事务不保证原子性(一致性),就没有回滚的概念了.事务中任何命令的失败,其余命令任会执行
可以这么说.Redis的以上两个事务特征几乎可以认为,redis没有事务功能.更应该称之为命令的打包执行.
那么为什么redis中要有事务?举个例子:假设登录的时候记录登录的ip(一条命令操作),接下再执行保存用户的登录消息操作(一条命令),假设获取用户的消息需要在另外一个系统中获取,我们无法保证100%获取到.但是这两步操作在我们程序业务功能设计中应该被认为是登录操作的单个功能起的影响.因为获取用户的登录消息可能会失败.那么就没必要记录ip了.redis恰恰提供事务名队列的清空功能
可以怎么理解,如果你的(命令)操作步骤非常多,每一个命令都需要大量的其他非redis的操作才能保证接下来的业务进行,那么就需要redis的事务队列功能一步一步记录命令,在整个工程中如果发生了意外则清空队列,正常则提交
所以我们应该在我们的程序代码中保证一致性和隔离级别的功能而不是交给redis,方正redis的事务就是打包执行,任何利用是查询设计的问题
在redis开启事务的魅力multi
就可以知道,redis自己本身也没有把这个功能称之为事务.正确的叫法是多命令
3.若在待执行队列
中存在语法性错误,exec
提交之后,其他正确命令也会被执行,这是单单的错误命令抛出异常
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set name li si #错误的命令
QUEUED
127.0.0.1:6379> set money 100
QUEUED
127.0.0.1:6379> exec
1) (error) ERR syntax error
2) OK
如果是错误的命令名(比如
setnx
写成setnn
,则不能称之为语法错误),如果在队列中出现了类似错误,则整个队列不成功
watch
语法:watch key
watch类似于乐观锁
如果在watch
命令观测一个key
之后,开启事务后修改该key
.这个时候如果有其它连接修改了key
,则会导致事务执行失败,在这个事务的其他操作也是失败
exec
之后,watch
命令监控取消
watch
命令可以说是redis的事务功能最关键的运用了,在使用了watch
之后可以保证一定的原子性和数据安全