网站建设相关博客,西安网络公司,网站服务器租用一年多少钱啊,手机大全什么是Redis事务
Redis 事务的本质是一组命令的集合。事务支持一次执行多个命令#xff0c;一个事务中所有命令都会被序列化。在事务执行过程#xff0c;会按照顺序串行化执行队列中的命令#xff0c;其他客户端提交的命令请求不会插入到事务执行命令序列中。
总结说…什么是Redis事务
Redis 事务的本质是一组命令的集合。事务支持一次执行多个命令一个事务中所有命令都会被序列化。在事务执行过程会按照顺序串行化执行队列中的命令其他客户端提交的命令请求不会插入到事务执行命令序列中。
总结说redis事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令。 Redis事务相关命令和使用 MULTI 、 EXEC 、 DISCARD 和 WATCH 是 Redis 事务相关的命令。 MULTI 开启事务redis会将后续的命令逐个放入队列中然后使用EXEC命令来原子化执行这个命令系列。EXEC执行事务中的所有操作命令。DISCARD取消事务放弃执行事务块中的所有命令。WATCH监视一个或多个key,如果事务在执行前这个key(或多个key)被其他命令修改则事务被中断不会执行事务中的任何命令。UNWATCH取消WATCH对所有key的监视。
标准的事务执行
给k1、k2分别赋值在事务中修改k1、k2执行事务后查看k1、k2值都被修改。
127.0.0.1:6379 set k1 v1
OK
127.0.0.1:6379 set k2 v2
OK
127.0.0.1:6379 MULTI
OK
127.0.0.1:6379 set k1 11
QUEUED
127.0.0.1:6379 set k2 22
QUEUED
127.0.0.1:6379 EXEC
1) OK
2) OK
127.0.0.1:6379 get k1
11
127.0.0.1:6379 get k2
22
127.0.0.1:6379
事务取消
127.0.0.1:6379 MULTI
OK
127.0.0.1:6379 set k1 33
QUEUED
127.0.0.1:6379 set k2 34
QUEUED
127.0.0.1:6379 DISCARD
OK事务出现错误的处理
语法错误编译器错误
在开启事务后修改k1值为11k2值为22但k2语法错误最终导致事务提交失败k1、k2保留原值。
127.0.0.1:6379 set k1 v1
OK
127.0.0.1:6379 set k2 v2
OK
127.0.0.1:6379 MULTI
OK
127.0.0.1:6379 set k1 11
QUEUED
127.0.0.1:6379 sets k2 22
(error) ERR unknown command sets, with args beginning with: k2, 22,
127.0.0.1:6379 exec
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379 get k1
v1
127.0.0.1:6379 get k2
v2
127.0.0.1:6379Redis类型错误运行时错误
在开启事务后修改k1值为11k2值为22但将k2的类型作为List在运行时检测类型错误最终导致事务提交失败此时事务并没有回滚而是跳过错误命令继续执行 结果k1值改变、k2保留原值
127.0.0.1:6379 set k1 v1
OK
127.0.0.1:6379 set k1 v2
OK
127.0.0.1:6379 MULTI
OK
127.0.0.1:6379 set k1 11
QUEUED
127.0.0.1:6379 lpush k2 22
QUEUED
127.0.0.1:6379 EXEC
1) OK
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379 get k1
11
127.0.0.1:6379 get k2
v2
127.0.0.1:6379
CAS操作实现乐观锁 WATCH 命令可以为 Redis 事务提供 check-and-set CAS行为。 被 WATCH 的键会被监视并会发觉这些键是否被改动过了。 如果有至少一个被监视的键在 EXEC 执行之前被修改了 那么整个事务都会被取消 EXEC 返回nil-reply来表示事务已经失败。
举个例子 假设我们需要原子性地为某个值进行增 1 操作假设 INCR 不存在。
val GET mykey
val val 1
SET mykey $val
上面的这个实现在只有一个客户端的时候可以执行得很好。 但是 当多个客户端同时对同一个键进行这样的操作时 就会产生竞争条件。举个例子 如果客户端 A 和 B 都读取了键原来的值 比如 10 那么两个客户端都会将键的值设为 11 但正确的结果应该是 12 才对。
有了 WATCH 我们就可以轻松地解决这类问题了
WATCH mykey
val GET mykey
val val 1
MULTI
SET mykey $val
EXEC
使用上面的代码 如果在 WATCH 执行之后 EXEC 执行之前 有其他客户端修改了 mykey 的值 那么当前客户端的事务就会失败。 程序需要做的 就是不断重试这个操作 直到没有发生碰撞为止。
这种形式的锁被称作乐观锁 它是一种非常强大的锁机制。 并且因为大多数情况下 不同的客户端会访问不同的键 碰撞的情况一般都很少 所以通常并不需要进行重试。 watch是如何监视实现的呢
Redis使用WATCH命令来决定事务是继续执行还是回滚那就需要在MULTI之前使用WATCH来监控某些键值对然后使用MULTI命令来开启事务执行对数据结构操作的各种命令此时这些命令入队列。
当使用EXEC执行事务时首先会比对WATCH所监控的键值对如果没发生改变它会执行事务队列中的命令提交事务如果发生变化将不会执行事务中的任何命令同时事务回滚。当然无论是否回滚Redis都会取消执行事务前的WATCH命令。 watch 命令实现监视
在事务开始前用WATCH监控k1之后修改k1为11说明事务开始前k1值被改变MULTI开始事务修改k1值为12k2为22执行EXEC发回nil说明事务回滚查看下k1、k2的值都没有被事务中的命令所改变。
127.0.0.1:6379 set k1 v1
OK
127.0.0.1:6379 set k2 v2
OK
127.0.0.1:6379 WATCH k1
OK
127.0.0.1:6379 set k1 11
OK
127.0.0.1:6379 MULTI
OK
127.0.0.1:6379 set k1 12
QUEUED
127.0.0.1:6379 set k2 22
QUEUED
127.0.0.1:6379 EXEC
(nil)
127.0.0.1:6379 get k1
11
127.0.0.1:6379 get k2
v2
127.0.0.1:6379 Redis事务执行步骤
通过上文命令执行很显然Redis事务执行是三个阶段 开启以MULTI开始一个事务 入队将多个命令入队到事务中接到这些命令并不会立即执行而是放到等待执行的事务队列里面 执行由EXEC命令触发事务
当一个客户端切换到事务状态之后 服务器会根据这个客户端发来的不同命令执行不同的操作
如果客户端发送的命令为 EXEC 、 DISCARD 、 WATCH 、 MULTI 四个命令的其中一个 那么服务器立即执行这个命令。与此相反 如果客户端发送的命令是 EXEC 、 DISCARD 、 WATCH 、 MULTI 四个命令以外的其他命令 那么服务器并不立即执行这个命令 而是将这个命令放入一个事务队列里面 然后向客户端返回 QUEUED 回复。 更深入的理解 我们再通过几个问题来深入理解Redis事务。 为什么 Redis 不支持回滚 如果你有使用关系式数据库的经验 那么 “Redis 在事务失败时不进行回滚而是继续执行余下的命令”这种做法可能会让你觉得有点奇怪。 以下是这种做法的优点
Redis 命令只会因为错误的语法而失败并且这些问题不能在入队时发现或是命令用在了错误类型的键上面这也就是说从实用性的角度来说失败的命令是由编程错误造成的而这些错误应该在开发的过程中被发现而不应该出现在生产环境中。因为不需要对回滚进行支持所以 Redis 的内部可以保持简单且快速。
有种观点认为 Redis 处理事务的做法会产生 bug 然而需要注意的是 在通常情况下 回滚并不能解决编程错误带来的问题。 举个例子 如果你本来想通过 INCR 命令将键的值加上 1 却不小心加上了 2 又或者对错误类型的键执行了 INCR 回滚是没有办法处理这些情况的。
如何理解Redis与事务的ACID 一般来说事务有四个性质称为ACID分别是原子性一致性隔离性和持久性。这是基础但是很多文章对Redis 是否支持ACID有一些异议我觉的有必要梳理下 原子性atomicity
首先通过上文知道 运行期的错误是不会回滚的很多文章由此说Redis事务违背原子性的而官方文档认为是遵从原子性的。
Redis官方文档给的理解是Redis的事务是原子性的所有的命令要么全部执行要么全部不执行。而不是完全成功。
一致性consistency
redis事务可以保证命令失败的情况下得以回滚数据能恢复到没有执行之前的样子是保证一致性的除非redis进程意外终结。
一致性consistency
redis事务可以保证命令失败的情况下得以回滚数据能恢复到没有执行之前的样子是保证一致性的除非redis进程意外终结。但是Redis不像其它结构化数据库有隔离级别这种设计。
持久性Durability
redis事务是不保证持久性的这是因为redis持久化策略中不管是RDB还是AOF都是异步执行的不保证持久性是出于对性能的考虑。