1 事务
2 用法
3 回滚命令队列
4 用 check-and-set 进行乐观锁定
5 关于 WATCH 的说明
6 用 WATCH 实现 ZPOP
事务
MULTI, EXEC, DISCARD 和 WATCH 是 Redis 事务的基础。他们允许一次执行一组命令,并有两项重要保证:
在一个事务中的所有命令是连续执行的。在一个 Redis 事务的执行过程中绝不会有另一个客户端发出的请求被处理。这保证了这些命令被作为单一原子操作执行。
要末所有命令都被执行,要末什么都不执行。在事务中,由 EXEC 命令触发执行所有的命令。因此如果一个客户端在事务环境中执行 MULTI 命令之前和服务器的连接中断(译者注:也许这句话里说的应该是 EXEC 命令而不是 MULIT 命令),将不会有任何命令被执行,反之如果 EXEC 命令被调用,则所有操作都会被执行。当使用 append-only file 时,Redis 会使用 a single write(2) syscall 来确保事务写入磁盘。然而如果 Redis 服务器崩溃或者被系统管理员毫不客气的 kill 掉,有可能只有部分操作被登记。Redis 将在启动时检测到这种情况,并退出和返回错误。使用 redis-check-aof 工具有可能修复 append only file,它会删除不完整的事务以便服务器能再次重启。
除了上面两条,Redis 2.2 还提供了一项额外的保证,它以乐观锁定的形提供一种方法,非常类似 check-and-set (CAS) (译者注:条件设置,条件符合则设置,不符合则取消)操作。这在本文后面会讲述。
用法
用 MULTI 命令进入一个 Redis 事务。这个命令总是返回成功。这时候用户可以提交多个命令。Redis 不会立即执行他们,而是将他们排入队列。一旦调用 EXEC 命令,所有的命令就会被执行。
而调用 DISCARD 将会清空事务的命令队列并退出事务。
下面的例子原子的增加键 foo 和 bar 的值
> MULTI
OK
> INCR foo
QUEUED
> INCR bar
QUEUED
> EXEC
1) (integer) 1
2) (integer) 1
从上面的例子中可以看到,MULTI 命令返回一个返回值数组,其中每个元素就是事务中单个命令的返回值,他们的顺序就是命令执行的顺序。
When a Redis connection is in the context of a MULTI request, all commands will reply with the string QUEUED unless they are syntactically incorrect. Some commands are still allowed to fail during execution time.
当一个 Redis 连接处于 MULTI 请求之中时,所有命令将返回字符串 QUEUED,除非有语法错误。命令可以在执行过程中失败。
这在协议层面上更清晰,下面的例子中,虽然语法都是正确的,但还是有一个命令在执行过程中失败。
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
MULTI
+OK
SET a 3
abc
+QUEUED
LPOP a
+QUEUED
EXEC
*2
+OK
-ERR Operation against a key holding the wrong kind of value
MULTI 返回包含两个元素的 Bulk reply ,一个是 OK,另一个是 -ERR。客户端可据此向用户提供更合适的错误输出。
需要注意的是:即使一个命令执行失败,所有其他的命令还是会被执行 – Redis 不会终止命令的执行过程。
再来一个例子,我们还使用 telnet 协议,可以看到语法错误何时被报告,相对执行错误,语法错误会立即报告给客户端。
MULTI
+OK
INCR a b c
-ERR wrong number of arguments for 'incr' command
这次由于语法错误,这个糟糕的 INCR 命令根本不会被放入事务的命令队列。
回滚命令队列
DISCARD 被用于取消事务。在这种情况下,没有命令会被执行,并且连接的状态会从事务状态恢复到正常状态。
> SET foo 1
OK
> MULTI
OK
> INCR foo
QUEUED
> DISCARD
OK
> GET foo
"1"
用 check-and-set 进行乐观锁定
WATCH 为 Redis 事务提供了 check-and-set (CAS) 特性。
行如其名,WATCH 会监视被其“看管”的每个键。如果在 EXEC 命令之前,有至少一个键被修改了,整个事务将会取消,并且 EXEC 命令返回一个 Null multi-bulk 返回值 来告知客户端事务失败了。
例如,设想我们需要对一个键值加1(假设不存在 INCR 这个方便的命令)
首先会尝试这么做:
val = GET mykey
val = val + 1
SET mykey $val
如果我们只有一个单客户端在做这个操作,那么这段代码是可靠的。如果有多个客户端在几乎相同的时刻试图增加这个键值,会导致竞争状态。例如,客户端 A 和 B 会读取原值,假设原值是 10。经过加法操作,两个客户端都得到 11,最后将 11 SET 为键值。所以最终的键值是 11 而不是 12 。
感谢 WATCH 让我能够非常好的处理此类问题:
WATCH mykey
val = GET mykey
val = val + 1
MULTI
SET mykey $val
EXEC
用上面的代码,如果出现竞争状态:另一个客户端在我们调用 WATCH 和 EXEC 之间的过程中修改了 val 的值,事务将不会执行。
我们只是需要重复这些操作,以期待这次不要再出现新的竞争。这种锁定被称为乐观锁定,这是一种非常激进的锁定形式。在多数情况下,多个客户端会访问不同的键,因此碰撞不会发生,通常不需要重复执行这个操作(译者注:在概率上避免了多次循环造成性能低下或者死锁,如果调用者觉得不安全完全可以自己加计数器防止死锁)。
关于 WATCH 的说明
那么 WATCH 实际上做了什么呢?他会让 EXEC 有附加条件:我们在请求 Redis 完成事务,但仅当没有其他客户端修改任何被 WATCH “监视”的键值时。否则事务将根本不会被进入。(注意:如果 WATCH 一个很容易过期的键,并且在 WATCH 它之后 Redis 就使其期满失效,EXEC 将继续工作。预知详情请点这里。)
WATCH 可以被调用多次。 WATCH 仅在自身调用点和 EXEC 的调用点之间监视键值变化。你也可以向单个 WATCH 语句传递任意数量的键值。
当 EXEC 被调用后,所有的之前被监视的键值会被取消监视,不管事务是否被取消或者执行。并且当客户端连接丢失的时候,所有东西都会被取消监视。
It is also possible to use the UNWATCH command (without arguments) in order to flush all the watched keys. Sometimes this is useful as we optimistically lock a few keys, since possibly we need to perform a transaction to alter those keys, but after reading the current content of the keys we don’t want to proceed. When this happens we just call UNWATCHso that the connection can already be used freely for new transactions.
为了清除键值的被监视状态,也可以使用 UNWATCH 命令(没有参数)。有时这在乐观锁定某些键时有用,因为有可能我们要在事务中修改这些键值,但读取这些键值的内容后又不想修改了。这种情况下,只需调用 UNWATCH 即可。
用 WATCH 实现 ZPOP
有个不错的例子,和大家分享一下,演示用 WATCH 如何创建目前不被 Redis 内置支持的原子操作 — 实现 ZPOP,这个命令会原子的从有序集合( sorted set )弹出较低分值(score)的元素。下面是个最简单的实现:
WATCH zset
element = ZRANGE zset 0 0
MULTI
ZREM zset element
EXEC
如果 EXEC 失败(例如返回 Null multi-bulk reply)我们只需重复这些操作。
分享到:
相关推荐
**Redis与LabVIEW的整合:RedisinLabVIEW和LabVIEWRedis工具包** Redis是一个高性能的键值数据库,常用于数据缓存和消息队列。它支持丰富的数据类型,包括字符串、哈希表、列表、集合和有序集合。在LabVIEW...
Redis 是一个开源的内存数据结构存储系统,常被用作数据库、缓存和消息代理。在Windows环境下,Redis 的安装和使用与在Linux系统中有所不同。这里我们将详细讨论Windows版Redis 5.0.14的相关知识点。 1. **Redis ...
最近需要在C#中使用Redis,在Redis的官网找到了ServiceStack.Redis,最后在测试的时候发现这是个坑,4.0已上已经收费,后面只好找到3系列的最终版本,最后测试发现还是有BUG或者是我不会用。没有办法,最好找到了...
在Linux系统中安装Redis是一个常见的任务,特别是在搭建服务器或开发基于Redis的数据缓存应用时。Redis是一个开源的、高性能的键值对存储系统,适用于数据缓存、消息队列等多种场景。本文将详细介绍如何在Linux上...
Redis,全称Remote Dictionary Server,是一款开源的、高性能的键值存储系统,广泛应用于缓存、消息队列、数据持久化等多种场景。它以其高效、轻量级的特性,在IT行业中备受青睐,尤其是在互联网领域。在Windows环境...
Redis,全称Remote Dictionary Server,是一款开源的、高性能的键值对存储系统,常被用作数据缓存、消息队列以及数据库等角色。它的设计目标是速度和数据持久化,支持多种数据结构,如字符串、哈希表、列表、集合、...
redis部署6.2.6最新稳定版文档和程序redis部署6.2.6最新稳定版文档和程序redis部署6.2.6最新稳定版文档和程序redis部署6.2.6最新稳定版文档和程序redis部署6.2.6最新稳定版文档和程序redis部署6.2.6最新稳定版文档和...
Redis是一款高性能的键值对数据库,常用于缓存、消息队列等场景。在Windows操作系统上运行Redis,通常需要借助一些额外的工具。标题提到的"redis在win上的运行脚本redis.bat"就是一个帮助用户在Windows环境下启动...
Redis是世界上最受欢迎的开源内存数据结构存储系统,它可以用作数据库、缓存和消息代理。在Windows 64位环境下,Redis的安装和卸载过程是很多开发者和系统管理员需要了解的重要技能。以下是对这些知识点的详细说明:...
Redis Desktop Manager是一款强大的开源图形化界面工具,专为管理和操作Redis键值存储系统而设计。它为用户提供了直观且高效的界面,使得在处理Redis数据库时能够更加便捷。这个压缩包包含的就是这款工具的安装文件...
Redis是一款高性能的键值对内存数据库,被广泛应用于缓存、数据存储等领域。在这个Windows 64位版本的Redis 7.0.5中,我们能够看到一系列关键组件和配置文件,这使得它能够在Windows环境下运行。以下是关于Redis ...
Redis7.0.4.zip,解压缩到D盘根目录后,安装后启动为Windows服务 注意是windows 64位系统才可使用,不支持windows 32位系统使用 已经在Win10,Win11,Windows server 2012系统测试运行可用 使用步骤注意事项: ...
基于前后端分离的应用,无论是否使用Redis,都需要考虑如何进行数据的存储和缓存。下面我将分别介绍基于Redis和无Redis的两种版本的特点。 基于Redis的版本 特点 缓存处理:Redis作为内存数据库可以用来缓存频繁访问...
Redis 是一个高性能的键值数据库,它以键值对的形式存储数据,广泛应用于缓存、消息中间件、实时分析等领域。在 Windows 环境下,通常需要通过安装过程来设置 Redis 服务,但这里提供的资源是“redis 免安装”,意味...
在Windows上安装Redis的过程涉及到多个步骤,包括启用必要的Windows功能、安装WSL2(Windows Subsystem for Linux 2)、设置默认WSL版本以及在Linux环境中安装Redis。以下是对这些步骤的详细说明: 1. **启用...
Redis,全称Remote Dictionary Server,是一款高性能的键值存储数据库,常用于缓存、消息队列等场景。本文将深入探讨Redis的可视化工具及其免安装绿色版的使用,帮助你更好地管理和操作Redis服务器。 首先,了解...
Redis 使用教程详解 Redis 是一个高性能的 NoSQL 键值存储数据库,广泛应用于缓存、任务列表、网站访问统计数据、过期处理、应用排行榜、分布式集群架构中的 session 分离等领域。下面是 Redis 的详细使用教程。 ...
(1)支持Lua脚本:Redis 3.0支持Lua脚本,可以在Redis中执行脚本,大大提高了Redis的灵活性和可扩展性; (2)可插拔模块化:Redis 3.0提供了可插拔的模块化功能,可以根据用户的需求,自定义模块,实现不同的功能...
Redis是一款高性能的键值存储系统,常用于数据库、缓存和消息代理等场景。它支持丰富的数据类型,如字符串、哈希、列表、集合和有序集合。在Windows平台上使用Redis,通常需要通过编译源码或者寻找预编译的二进制...
"Redis++使用说明,windows下编译Redis-Plus-Plus" 在这篇文章中,我们将详细介绍如何在Windows平台下编译Redis++,包括编译hiredis.lib和Win32_Interop.lib静态库文件的过程,然后安装Cmake并编译Redis++,最后...