命令英文 | 命令中文 | 成功 | 失败 | 解释 | |
---|---|---|---|---|---|
multi | 开启事务 | OK | |||
set/get… | 各种命令 | 全都返回"QUEUED" |
整个事务取消,但不会回滚之前的命令 | ||
watch key | 监视 | exec成功 | exec失败 | watch到exec这段时间值被其他客户端改了exec就错误 | |
exec | 执行事务 | 返回所有的结果 | (nil) |
||
discard | 取消事务 |
Redis 作者认为发生事务回滚的原因大部分都是程序错误导致,这种情况一般发生在开发和测试阶段,而生产环境很少出现。
对于逻辑性错误,比如本来应该把一个数加 1 ,但是程序逻辑写成了加 2,那么这种错误也是无法通过事务回滚来进行解决的。
Redis 追求的是简单高效,而传统事务的实现相对比较复杂,这和 Redis 的设计思想相违背。
总结:redis不会错,错了就是你的错,我就这样
C - 一致性
一致性指的就是事务执行前后的数据符合数据库的定义和要求。这一点 Redis 中的事务是符合要求的,上面讲述原子性的时候已经提到,不论是发生语法错误还是运行时错误,错误的命令均不会被执行。
I - 隔离性
事务中的所有命令都会按顺序执行,在执行 Redis 事务的过程中,另一个客户端发出的请求不可能被服务,这保证了命令是作为单独的独立操作执行的。所以 Redis 当中的事务是符合隔离性要求的。
D - 持久性
如果 Redis 当中没有被开启持久化,那么就是纯内存运行的,一旦重启,所有数据都会丢失,此时可以认为 Redis 不具备事务的持久性;而如果 Redis 开启了持久化,那么可以认为 Redis 在特定条件下是具备持久性的。
Redis 中每个客户端都有记录当前客户端的事务状态 multiState,下面就是一个客户端 client 的数据结构定义:
typedef struct client {
uint64_t id;//客户端唯一 id
multiState mstate; //MULTI 和 EXEC 状态(即事务状态)
//...省略其他属性
} client;
multiState 数据结构定义如下:
typedef struct multiState {
multiCmd *commands;//存储命令的 FIFO 队列
int count;//命令总数
//...省略了其他属性
} multiState;
multiCmd 是一个队列,用来接收并存储开启事务之后发送的命令,其数据结构定义如下:
typedef struct multiCmd {
robj **argv;//用来存储参数的数组
int argc;//参数的数量
struct redisCommand *cmd;//命令指针
} multiCmd;