以下实例讲解了如何启动 redis 客户端:

启动 redis 客户端,打开终端并输入命令 redis-cli。该命令会连接本地的 redis 服务。

$redis-cli
redis 127.0.0.1:>
redis 127.0.0.1:> PING PONG

在远程服务上执行命令

如果需要在远程 redis 服务上执行命令,同样我们使用的也是 redis-cli 命令。

语法

$ redis-cli -h host -p port -a password

实例

以下实例演示了如何连接到主机为 127.0.0.1,端口为 6379 ,密码为 mypass 的 redis 服务上。

$redis-cli -h 127.0.0.1 -p  -a "mypass"
redis 127.0.0.1:>
redis 127.0.0.1:> PING PONG

有时候会有中文乱码。

要在 redis-cli 后面加上 --raw

redis-cli --raw

Redis Expire 命令用于设置 key 的过期时间,key 过期后将不再可用。单位以秒计。

设置成功返回 1 。 当 key 不存在或者不能为 key 设置过期时间时(比如在低于 2.1.3 版本的 Redis 中你尝试更新 key 的过期时间)返回 0 。

redis> SET mykey "Hello"
OK redis> EXPIRE mykey # 为 key 设置生存时间
(integer) redis> TTL mykey
(integer) redis> PERSIST mykey # 移除 key 的生存时间
(integer) redis> TTL mykey 以秒为单位,返回给定 key 的剩余生存时间(TTL, time to live)。
(integer) -
返回 key 的数据类型,数据类型有:
# 字符串 redis> SET weather "sunny"
OK redis> TYPE weather
string # 列表 redis> LPUSH book_list "programming in scala"
(integer) redis> TYPE book_list
list # 集合 redis> SADD pat "dog"
(integer) redis> TYPE pat
set

Redis Getrange 命令用于获取存储在指定 key 中字符串的子字符串。字符串的截取范围由 start 和 end 两个偏移量决定(包括 start 和 end 在内)。

redis 127.0.0.1:> SET mykey "This is my test key"
OK
redis 127.0.0.1:> GETRANGE mykey
"This"
redis 127.0.0.1:> GETRANGE mykey -
"This is my test key"

Redis Getset 命令用于设置指定 key 的值,并返回 key 的旧值。

返回给定 key 的旧值。 当 key 没有旧值时,即 key 不存在时,返回 nil 。

当 key 存在但不是字符串类型时,返回一个错误。

redis> GETSET db mongodb    # 没有旧值,返回 nil
(nil) redis> GET db
"mongodb" redis> GETSET db redis # 返回旧值 mongodb
"mongodb" redis> GET db
"redis"

Redis Getset 命令用于设置指定 key 的值,并返回 key 的旧值。

127.0.0.1:> get k3
"redis"
127.0.0.1:> getset k3 abc
"redis"
127.0.0.1:> get k3
"abc"

Redis Mget 命令返回所有(一个或多个)给定 key 的值。 如果给定的 key 里面,有某个 key 不存在,那么这个 key 返回特殊值 nil 。

redis 127.0.0.1:> SET key1 "hello"
OK
redis 127.0.0.1:> SET key2 "world"
OK
redis 127.0.0.1:> MGET key1 key2 someOtherKey
) "Hello"
) "World"
) (nil)

Redis Strlen 命令用于获取指定 key 所储存的字符串值的长度。当 key 储存的不是字符串值时,返回一个错误。

127.0.0.1:> get k3
"abc"
127.0.0.1:> strlen k3
(integer)
127.0.0.1:> keys *
) "k3"
) "mong"
127.0.0.1:> strlen k1
(integer)

Redis Incr 命令将 key 中储存的数字值增一。

如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作。

如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。

本操作的值限制在 64 位(bit)有符号数字表示之内。

redis> SET page_view
OK redis> INCR page_view
(integer) redis> GET page_view # 数字值在 Redis 中以字符串的形式保存
""

Redis Incrby 命令将 key 中储存的数字加上指定的增量值。

如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCRBY 命令。

如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。

本操作的值限制在 64 位(bit)有符号数字表示之内。

# key 存在且是数字值

redis> SET rank
OK redis> INCRBY rank
(integer) redis> GET rank
"" # key 不存在时 redis> EXISTS counter
(integer) redis> INCRBY counter
(integer) redis> GET counter
"" # key 不是数字值时 redis> SET book "long long ago..."
OK redis> INCRBY book
(error) ERR value is not an integer or out of range

Redis Hdel 命令用于删除哈希表 key 中的一个或多个指定字段,不存在的字段将被忽略。

redis 127.0.0.1:> HSET myhash field1 "foo"
(integer)
redis 127.0.0.1:> HDEL myhash field1
(integer)
redis 127.0.0.1:> HDEL myhash field2
(integer)

Redis Hexists 命令用于查看哈希表的指定字段是否存在。

如果哈希表含有给定字段,返回 1 。 如果哈希表不含有给定字段,或 key 不存在,返回 0 。

redis 127.0.0.1:> HSET myhash field1 "foo"
(integer)
redis 127.0.0.1:> HEXISTS myhash field1
(integer)
redis 127.0.0.1:> HEXISTS myhash field2
(integer)

Redis Hget 命令用于返回哈希表中指定字段的值。

# 字段存在

redis> HSET site redis redis.com
(integer) redis> HGET site redis
"redis.com" # 字段不存在 redis> HGET site mysql
(nil)
redis> HSET myhash field1 "Hello"
(integer)
redis> HSET myhash field2 "World"
(integer)
redis> HGETALL myhash
) "field1"
) "Hello"
) "field2"
) "World"
redis>

Redis Hincrby 命令用于为哈希表中的字段值加上指定增量值。

增量也可以为负数,相当于对指定字段进行减法操作。

如果哈希表的 key 不存在,一个新的哈希表被创建并执行 HINCRBY 命令。

如果指定的字段不存在,那么在执行命令前,字段的值被初始化为 0 。

对一个储存字符串值的字段执行 HINCRBY 命令将造成一个错误。

本操作的值被限制在 64 位(bit)有符号数字表示之内。

redis> HSET myhash field
(integer)
redis> HINCRBY myhash field
(integer)
redis> HINCRBY myhash field -
(integer)
redis> HINCRBY myhash field -
(integer) -
redis>

Redis Hkeys 命令用于获取哈希表中的所有域(field)。

redis 127.0.0.1:> HSET myhash field1 "foo"
(integer)
redis 127.0.0.1:> HSET myhash field2 "bar"
(integer)
redis 127.0.0.1:> HKEYS myhash
) "field1"
) "field2"

Redis Hmset 命令用于同时将多个 field-value (字段-值)对设置到哈希表中。

此命令会覆盖哈希表中已存在的字段。

如果哈希表不存在,会创建一个空哈希表,并执行 HMSET 操作。

redis 127.0.0.1:> HMSET myhash field1 "Hello" field2 "World"
OK
redis 127.0.0.1:> HGET myhash field1
"Hello"
redis 127.0.0.1:> HGET myhash field2
"World"

Redis Hlen 命令用于获取哈希表中字段的数量。

哈希表中字段的数量。 当 key 不存在时,返回 0 。
redis 127.0.0.1:> HSET myhash field1 "foo"
(integer)
redis 127.0.0.1:> HSET myhash field2 "bar"
(integer)
redis 127.0.0.1:> HLEN myhash
(integer)

Redis Hmget 命令用于返回哈希表中,一个或多个给定字段的值。

如果指定的字段不存在于哈希表,那么返回一个 nil 值。

一个包含多个给定字段关联值的表,表值的排列顺序和指定字段的请求顺序一样。

redis 127.0.0.1:> HSET myhash field1 "foo"
(integer)
redis 127.0.0.1:> HSET myhash field2 "bar"
(integer)
redis 127.0.0.1:> HMGET myhash field1 field2 nofield
) "foo"
) "bar"
) (nil)

Redis Hmset 命令用于同时将多个 field-value (字段-值)对设置到哈希表中。

此命令会覆盖哈希表中已存在的字段。

如果哈希表不存在,会创建一个空哈希表,并执行 HMSET 操作。

如果命令执行成功,返回 OK 。

redis 127.0.0.1:> HMSET myhash field1 "Hello" field2 "World"
OK
redis 127.0.0.1:> HGET myhash field1
"Hello"
redis 127.0.0.1:> HGET myhash field2
"World"

Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。

Redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。

集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。

127.0.0.1:> sadd l1 k1
(integer)
127.0.0.1:> sadd l1 k2
(integer)
127.0.0.1:> sadd l1 k3
(integer)
127.0.0.1:> sget l1
(error) ERR unknown command `sget`, with args beginning with: `l1`,
127.0.0.1:> smembers l1
) "k3"
) "k1"
) "k2"
 

Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。

不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。

有序集合的成员是唯一的,但分数(score)却可以重复。

集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。

Redis Zadd 命令用于将一个或多个成员元素及其分数值加入到有序集当中。

如果某个成员已经是有序集的成员,那么更新这个成员的分数值,并通过重新插入这个成员元素,来保证该成员在正确的位置上。

分数值可以是整数值或双精度浮点数。

如果有序集合 key 不存在,则创建一个空的有序集并执行 ZADD 操作。

当 key 存在但不是有序集类型时,返回一个错误。

127.0.0.1:> zadd myzset  one
(integer)
127.0.0.1:> zadd myzset two
(integer)
127.0.0.1:> zadd myzset three four
127.0.0.1:> zrange myzset  - withscores
) "one"
) ""
) "two"
) ""
) "three"
) ""
) "four"
) ""
127.0.0.1:> zcard myzset
(integer)

Redis Zcard 命令用于计算集合中元素的数量。

Redis Zcount 命令用于计算有序集合中指定分数区间的成员数量。

分数值在 min 和 max 之间的成员的数量。

127.0.0.1:> zcount myzset
(integer)

Redis Zincrby 命令对有序集合中指定成员的分数加上增量 increment

可以通过传递一个负数值 increment ,让分数减去相应的值,比如 ZINCRBY key -5 member ,就是让 member 的 score 值减去 5 。

当 key 不存在,或分数不是 key 的成员时, ZINCRBY key increment member 等同于 ZADD key increment member 。

当 key 不是有序集类型时,返回一个错误。

分数值可以是整数值或双精度浮点数。

127.0.0.1:> zrange myzset  - withscores
) "one"
) ""
) "two"
) ""
) "three"
) ""
) "four"
) ""
127.0.0.1:> zincrby myzset one
""

Redis Zinterstore 命令计算给定的一个或多个有序集的交集,其中给定 key 的数量必须以 numkeys 参数指定,并将该交集(结果集)储存到 destination 。

默认情况下,结果集中某个成员的分数值是所有给定集下该成员分数值之和。

返回值

保存到目标结果集的的成员数量

# 有序集 mid_test
redis 127.0.0.1:> ZADD mid_test "Li Lei"
(integer)
redis 127.0.0.1:> ZADD mid_test "Han Meimei"
(integer)
redis 127.0.0.1:> ZADD mid_test 99.5 "Tom"
(integer) # 另一个有序集 fin_test
redis 127.0.0.1:> ZADD fin_test "Li Lei"
(integer)
redis 127.0.0.1:> ZADD fin_test "Han Meimei"
(integer)
redis 127.0.0.1:> ZADD fin_test 99.5 "Tom"
(integer) # 交集
redis 127.0.0.1:> ZINTERSTORE sum_point mid_test fin_test
(integer) # 显示有序集内所有成员及其分数值
redis 127.0.0.1:> ZRANGE sum_point - WITHSCORES
) "Han Meimei"
) ""
) "Li Lei"
) ""
) "Tom"
) ""

Redis Zrangebylex 通过字典区间返回有序集合的成员。

返回值

指定区间内的元素列表。

(integer)
redis 127.0.0.1:> ZRANGEBYLEX myzset - [c
) "a"
) "b"
) "c"
redis 127.0.0.1:> ZRANGEBYLEX myzset - (c
) "a"
) "b"
redis 127.0.0.1:> ZRANGEBYLEX myzset [aaa (g
) "b"
) "c"
) "d"
) "e"
) "f"
redis>

Redis Zrangebyscore 返回有序集合中指定分数区间的成员列表。有序集成员按分数值递增(从小到大)次序排列。

具有相同分数值的成员按字典序来排列(该属性是有序集提供的,不需要额外的计算)。

默认情况下,区间的取值使用闭区间 (小于等于或大于等于),你也可以通过给参数前增加 ( 符号来使用可选的开区间 (小于或大于)。

举个例子:

ZRANGEBYSCORE zset (1 5

返回所有符合条件 1 < score <= 5 的成员,而

ZRANGEBYSCORE zset (5 (10

则返回所有符合条件 5 < score < 10 的成员。

redis 127.0.0.1:> ZADD salary  jack                        # 测试数据
(integer)
redis 127.0.0.1:> ZADD salary tom
(integer)
redis 127.0.0.1:> ZADD salary peter
(integer) redis 127.0.0.1:> ZRANGEBYSCORE salary -inf +inf # 显示整个有序集
) "jack"
) "tom"
) "peter" redis 127.0.0.1:> ZRANGEBYSCORE salary -inf +inf WITHSCORES # 显示整个有序集及成员的 score 值
) "jack"
) ""
) "tom"
) ""
) "peter"
) "" redis 127.0.0.1:> ZRANGEBYSCORE salary -inf WITHSCORES # 显示工资 <= 的所有成员
) "jack"
) ""
) "tom"
) "" redis 127.0.0.1:> ZRANGEBYSCORE salary ( # 显示工资大于 小于等于 的成员
) "peter"

Redis Zrank 返回有序集中指定成员的排名。其中有序集成员按分数值递增(从小到大)顺序排列。

返回值

如果成员是有序集 key 的成员,返回 member 的排名。 如果成员不是有序集 key 的成员,返回 nil 。

redis 127.0.0.1:> ZRANGE salary  - WITHSCORES        # 显示所有成员及其 score 值
) "peter"
) ""
) "tom"
) ""
) "jack"
) "" redis 127.0.0.1:> ZRANK salary tom # 显示 tom 的薪水排名,第二
(integer)
redis 127.0.0.1:> ZRANGE salary  - WITHSCORES    # 测试数据
) "tom"
) ""
) "peter"
) ""
) "jack"
) "" redis 127.0.0.1:> ZSCORE salary peter

redis 的事务管理

Redis 事务可以一次执行多个命令, 并且带有以下两个重要的保证:

  • 批量操作在发送 EXEC 命令前被放入队列缓存。
  • 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。
  • 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。

一个事务从开始到执行会经历以下三个阶段:

  • 开始事务。
  • 命令入队。
  • 执行事务。
  • https://www.cnblogs.com/kyrin/p/5967620.html感谢博主我做个笔记
  • Redis会将一个事务中的所有命令序列化,然后按顺序执行。Redis不可能在一个Redis事务的执行过程中插入执行另一个客户端发出的请求。这样便能保证Redis将这些命令作为一个单独的隔离操作执行。 > 在一个Redis事务中,Redis要么执行其中的所有命令,要么什么都不执行。
  • 因此,Redis事务能够保证原子性。EXEC命令会触发执行事务中的所有命令。因此,当某个客户端正在执行一次事务时,如果它在调用MULTI命令之前就从Redis服务端断开连接,那么就不会执行事务中的任何操作;相反,如果它在调用EXEC命令之后才从Redis服务端断开连接,那么就会执行事务中的所有操作。当Redis使用只增文件(AOF:Append-only File)时,Redis能够确保使用一个单独的write(2)系统调用,这样便能将事务写入磁盘。然而,如果Redis服务器宕机,或者系统管理员以某种方式停止Redis服务进程的运行,那么Redis很有可能只执行了事务中的一部分操作。Redis将会在重新启动时检查上述状态,然后退出运行,并且输出报错信息。使用redis-check-aof工具可以修复上述的只增文件,这个工具将会从上述文件中删除执行不完全的事务,这样Redis服务器才能再次启动。
  • 一、相关命令

    1. MULTI

    用于标记事务块的开始。Redis会将后续的命令逐个放入队列中,然后才能使用EXEC命令原子化地执行这个命令序列。

    这个命令的运行格式如下所示:

    MULTI

    这个命令的返回值是一个简单的字符串,总是OK。

    2. EXEC

    在一个事务中执行所有先前放入队列的命令,然后恢复正常的连接状态。

    当使用WATCH命令时,只有当受监控的键没有被修改时,EXEC命令才会执行事务中的命令,这种方式利用了检查再设置(CAS)的机制。

    这个命令的运行格式如下所示:

    EXEC

    这个命令的返回值是一个数组,其中的每个元素分别是原子化事务中的每个命令的返回值。 当使用WATCH命令时,如果事务执行中止,那么EXEC命令就会返回一个Null值。

    3. DISCARD

    清除所有先前在一个事务中放入队列的命令,然后恢复正常的连接状态。

    如果使用了WATCH命令,那么DISCARD命令就会将当前连接监控的所有键取消监控。

    这个命令的运行格式如下所示:

    DISCARD

    这个命令的返回值是一个简单的字符串,总是OK。

    4. WATCH

    当某个事务需要按条件执行时,就要使用这个命令将给定的键设置为受监控的。

    这个命令的运行格式如下所示:

    WATCH key [key ...]

    这个命令的返回值是一个简单的字符串,总是OK。

    对于每个键来说,时间复杂度总是O(1)。

    5. UNWATCH

    清除所有先前为一个事务监控的键。

    如果你调用了EXEC或DISCARD命令,那么就不需要手动调用UNWATCH命令。

    这个命令的运行格式如下所示:

    UNWATCH

    这个命令的返回值是一个简单的字符串,总是OK。

    时间复杂度总是O(1)。

    二、使用方法

    使用MULTI命令便可以进入一个Redis事务。这个命令的返回值总是OK。此时,用户可以发出多个Redis命令。Redis会将这些命令放入队列,而不是执行这些命令。一旦调用EXEC命令,那么Redis就会执行事务中的所有命令。

    相反,调用DISCARD命令将会清除事务队列,然后退出事务。

    以下示例会原子化地递增foo键和bar键的值:

    正如从上面的会话所看到的一样,EXEC命令的返回值是一个数组,其中的每个元素都分别是事务中的每个命令的返回值,返回值的顺序和命令的发出顺序是相同的。

    当一个Redis连接正处于MULTI请求的上下文中时,通过这个连接发出的所有命令的返回值都是QUEUE字符串(从Redis协议的角度来看,返回值是作为状态回复(Status Reply)来发送的)。当调用EXEC命令时,Redis会简单地调度执行事务队列中的命令。

    三、事务内部的错误

    在一个事务的运行期间,可能会遇到两种类型的命令错误:

    一个命令可能会在被放入队列时失败。因此,事务有可能在调用EXEC命令之前就发生错误。例如,这个命令可能会有语法错误(参数的数量错误、命令名称错误,等等),或者可能会有某些临界条件(例如:如果使用maxmemory指令,为Redis服务器配置内存限制,那么就可能会有内存溢出条件)。 
    在调用EXEC命令之后,事务中的某个命令可能会执行失败。例如,我们对某个键执行了错误类型的操作(例如,对一个字符串(String)类型的键执行列表(List)类型的操作)。

    可以使用Redis客户端检测第一种类型的错误,在调用EXEC命令之前,这些客户端可以检查被放入队列的命令的返回值:如果命令的返回值是QUEUE字符串,那么就表示已经正确地将这个命令放入队列;否则,Redis将返回一个错误。如果将某个命令放入队列时发生错误,那么大多数客户端将会中止事务,并且丢弃这个事务。

    然而,从Redis 2.6.5版本开始,服务器会记住事务积累命令期间发生的错误。然后,Redis会拒绝执行这个事务,在运行EXEC命令之后,便会返回一个错误消息。最后,Redis会自动丢弃这个事务。

    在Redis 2.6.5版本之前,如果发生了上述的错误,那么在客户端调用了EXEC命令之后,Redis还是会运行这个出错的事务,执行已经成功放入事务队列的命令,而不会关心先前发生的错误。从2.6.5版本开始,Redis在遭遇上述错误时,会采用先前描述的新行为,这样便能轻松地混合使用事务和管道。在这种情况下,客户端可以一次性地将整个事务发送至Redis服务器,稍后再一次性地读取所有的返回值。

    相反,在调用EXEC命令之后发生的事务错误,Redis不会进行任何特殊处理:在事务运行期间,即使某个命令运行失败,所有其他的命令也将会继续执行。

    这种行为在协议层面上更加清晰。在以下示例中,当事务正在运行时,有一条命令将会执行失败,即使这条命令的语法是正确的:

    上述示例的EXEC命令的返回值是批量的字符串,包含两个元素,一个是OK代码,另一个是-ERR错误消息。客户端会根据自身的程序库,选择一种合适的方式,将错误信息提供给用户

    需要注意的是,即使某个命令执行失败,事务队列中的所有其他命令仍然会执行 —— Redis不会停止执行事务中的命令。

    再看另一个示例,再次使用telnet通信协议,观察命令的语法错误是如何尽快报告给用户的:

    这一次,由于INCR命令的语法错误,Redis根本就没有将这个命令放入事务队列。

    四、为什么Redis不支持回滚?

    如果你具备关系型数据库的知识背景,你就会发现一个事实:在事务运行期间,虽然Redis命令可能会执行失败,但是Redis仍然会执行事务中余下的其他命令,而不会执行回滚操作,你可能会觉得这种行为很奇怪。

    然而,这种行为也有其合理之处:

    只有当被调用的Redis命令有语法错误时,这条命令才会执行失败(在将这个命令放入事务队列期间,Redis能够发现此类问题),或者对某个键执行不符合其数据类型的操作:实际上,这就意味着只有程序错误才会导致Redis命令执行失败,这种错误很有可能在程序开发期间发现,一般很少在生产环境发现。 
    Redis已经在系统内部进行功能简化,这样可以确保更快的运行速度,因为Redis不需要事务回滚的能力。

    对于Redis事务的这种行为,有一个普遍的反对观点,那就是程序有可能会有缺陷(bug)。但是,你应当注意到:事务回滚并不能解决任何程序错误。例如,如果某个查询会将一个键的值递增2,而不是1,或者递增错误的键,那么事务回滚机制是没有办法解决这些程序问题的。请注意,没有人能解决程序员自己的错误,这种错误可能会导致Redis命令执行失败。正因为这些程序错误不大可能会进入生产环境,所以我们在开发Redis时选用更加简单和快速的方法,没有实现错误回滚的功能。

    五、丢弃命令队列

    DISCARD命令可以用来中止事务运行。在这种情况下,不会执行事务中的任何命令,并且会将Redis连接恢复为正常状态。示例如下所示:

    六、通过CAS操作实现乐观锁

    Redis使用WATCH命令实现事务的“检查再设置”(CAS)行为。

    作为WATCH命令的参数的键会受到Redis的监控,Redis能够检测到它们的变化。在执行EXEC命令之前,如果Redis检测到至少有一个键被修改了,那么整个事务便会中止运行,然后EXEC命令会返回一个Null值,提醒用户事务运行失败。

    例如,设想我们需要将某个键的值自动递增1(假设Redis没有INCR命令)。

    首次尝试的伪码可能如下所示:

    val = GET mykey
    val = val + 1
    SET mykey $val

    如果我们只有一个Redis客户端在一段指定的时间之内执行上述伪码的操作,那么这段伪码将能够可靠的工作。如果有多个客户端大约在同一时间尝试递增这个键的值,那么将会产生竞争状态。例如,客户端-A和客户端-B都会读取这个键的旧值(例如:10)。这两个客户端都会将这个键的值递增至11,最后使用SET命令将这个键的新值设置为11。因此,这个键的最终值是11,而不是12。

    现在,我们可以使用WATCH命令完美地解决上述的问题,伪码如下所示:

    WATCH mykey
    val = GET mykey
    val = val + 1
    MULTI
    SET mykey $val
    EXEC

    由上述伪码可知,如果存在竞争状态,并且有另一个客户端在我们调用WATCH命令和EXEC命令之间的时间内修改了val变量的结果,那么事务将会运行失败。

    我们只需要重复执行上述伪码的操作,希望此次运行不会再出现竞争状态。这种形式的锁就被称为乐观锁,它是一种非常强大的锁。在许多用例中,多个客户端可能会访问不同的键,因此不太可能发生冲突 —— 也就是说,通常没有必要重复执行上述伪码的操作。

    七、WATCH命令详解

    那么WATCH命令实际做了些什么呢?这个命令会使得EXEC命令在满足某些条件时才会运行事务:我们要求Redis只有在所有受监控的键都没有被修改时,才会执行事务。(但是,相同的客户端可能会在事务内部修改这些键,此时这个事务不会中止运行。)否则,Redis根本就不会进入事务。(注意,如果你使用WATCH命令监控一个易失性的键,然后在你监控这个键之后,Redis再使这个键过期,那么EXEC命令仍然可以正常工作。)

    WATCH命令可以被调用多次。简单说来,所有的WATCH命令都会在被调用之时立刻对相应的键进行监控,直到EXEC命令被调用之时为止。你可以在单条的WATCH命令之中,使用任意数量的键作为命令参数。

    当调用EXEC命令时,所有的键都会变为未受监控的状态,Redis不会管事务是否被中止。当一个客户单连接被关闭时,所有的键也都会变为未受监控的状态。

    你还可以使用UNWATCH命令(不需要任何参数),这样便能清除所有的受监控键。当我们对某些键施加乐观锁之后,这个命令有时会非常有用。因为,我们可能需要运行一个用来修改这些键的事务,但是在读取这些键的当前内容之后,我们可能不打算继续进行操作,此时便可以使用UNWATCH命令,清除所有受监控的键。在运行UNWATCH命令之后,Redis连接便可以再次自由地用于运行新事务。

    如何使用WATCH命令实现ZPOP操作呢?

    本文将通过一个示例,说明如何使用WATCH命令创建一个新的原子化操作(Redis并不原生支持这个原子化操作),此处会以实现ZPOP操作为例。这个命令会以一种原子化的方式,从一个有序集合中弹出分数最低的元素。以下源码是最简单的实现方式:

    WATCH zset
    element = ZRANGE zset 0 0
    MULTI
    ZREM zset element
    EXEC

    如果伪码中的EXEC命令执行失败(例如,返回Null值),那么我们只需要重复运行这个操作即可。

    八、Redis脚本和事务

    根据定义,Redis脚本也是事务型的。因此,你可以通过Redis事务实现的功能,同样也可以通过Redis脚本来实现,而且通常脚本更简单、更快速。

    由于Redis从2.6版本才开始引入脚本特性,而事务特性是很久以前就已经存在的,所以目前的版本才有两个看起来重复的特性。但是,我们不太可能在短时间内移除对事务特性的支持。因为,即使不用求助于Redis脚本,用户仍然能够规避竞争状态,这从语义上来看是适宜的。还有另一个更重要的原因,Redis事务特性的实现复杂度是最小的。

    但是,在相当长的一段时间之内,我们不大可能看到整个用户群体都只使用Redis脚本。如果发生这种情况,那么我们可能会废弃,甚至最终移除Redis事务。

redis 的简单命令的更多相关文章

  1. yum 安装redis 及简单命令(推荐测试环境,安装简单)

    第1章 redis 入门 1.1 yum 安装 安装repo源 cd /etc/yum.repos.d/ wget http://mirrors.aliyun.com/repo/epel-6.repo ...

  2. redis安装及简单命令

    Redis 安装 Window 下安装 下载地址:https://github.com/MSOpenTech/redis/releases. Redis 支持 32 位和 64 位.这个需要根据你系统 ...

  3. NoSQL之Redis高级实用命令详解--安全和主从复制

    Android IOS JavaScript HTML5 CSS jQuery Python PHP NodeJS Java Spring MySQL MongoDB Redis NOSQL Vim ...

  4. 基于Redis的简单分布式锁的原理

    参考资料:https://redis.io/commands/setnx 加锁是为了解决多线程的资源共享问题.Java中,单机环境的锁可以用synchronized和Lock,其他语言也都应该有自己的 ...

  5. 使用Redis模拟简单分布式锁,解决单点故障的问题

    需求描述: 最近做一个项目,项目中有一个功能,每天定时(凌晨1点)从数据库中获取需要爬虫的URL,并发送到对应的队列中,然后客户端监听对应的队列,然后执行任务.如果同时部署多个定时任务节点的话,每个节 ...

  6. Linux上面安装redis和简单使用

    一.安装,redis的官方的网址   https://redis.io/ 目前的最高的版本是4.0,我安装的是2.*的版本 1.下载源码,解压后编译源码. $ wget http://download ...

  7. 使用 Redis的SETNX命令实现分布式锁

    使用Redis的 SETNX 命令可以实现分布式锁,下文介绍其实现方法. SETNX命令简介 命令格式 SETNX key value 将 key 的值设为 value,当且仅当 key 不存在. 若 ...

  8. redis 之相关命令

    为什么缓存数据库更要首选redis?如何使用redis? 一.使用缓存数据库为什么首选用redis? 我们都知道,把一些热数据存到缓存中可以极大的提高速度,那么问题来了,是用Redis好还是Memca ...

  9. Redis主从复制简单介绍

    由于本地环境的使用,所以搭建一个本地的Redis集群,本篇讲解Redis主从复制集群的搭建,使用的平台是Windows,搭建的思路和Linux上基本一致! (精读阅读本篇可能花费您15分钟,略读需5分 ...

随机推荐

  1. 在PHP中管理环境变量

    在PHP中管理环境变量 现在我们都能用很多个编程语言开发,当我开始熟悉PHP时,我会忽略其它语言的特点.我用过其他语言(比如Node.js),但在PHP中没有看到一种轻松控制设置环境变量的方法,特别是 ...

  2. 复习centos7命令---vim常用

    1.如果想向下移动5行:在一般模式下按:5↓: 2.如果想想左右移动5行:在一般模式下按:5← 3.移动到一行的开头:一般模式下按:0 4.移动到一行的末尾:一般模式下按:$ 5.移动到屏幕中的第一行 ...

  3. 字符串类型的日期转化为Date类型

    //方法一:内部引用package com.th.mobula.test; import java.text.ParseException;import java.text.SimpleDateFor ...

  4. Unicode与UTF-8关系

    Unicode字符集合 Unicode 也称为 UCS(Universal Coded Character Set:国际编码字符集合) 是一个字符集合. 对世界上大部分的文字系统进行了整理,编码,使电 ...

  5. Springboot 实现api校验和登录验证

    https://blog.csdn.net/qq_36085004/article/details/83348144 文章目录 API校验 场景 实现思路 代码 拦截器: 拦截器注册: 登录token ...

  6. ASP.NET MVC]WebAPI应用支持HTTPS的经验总结

    WebAPI应用支持HTTPS的经验总结 在我前面介绍的WebAPI文章里面,介绍了WebAPI的架构设计方面的内容,其中提出了现在流行的WebAPI优先的路线,这种也是我们开发多应用(APP.微信. ...

  7. Python:Day35 mysql基础

    一.数据库管理系统DBMS 软件,存储数据 认证,授权,限制 SqlServer --- 微软(收费) Oracle,sqlite,access...MySQL 服务端和客户端 想要使用MySQL来存 ...

  8. 【window】Windows10下为PHP安装redis扩展

    操作: 步骤1:D:\wamp\bin\apache\apache2.4.9\bin/php.ini中添加 ; php_redis extension=php_igbinary.dll extensi ...

  9. 002_监测ssl证书过期时间

    一. s_client This implements a generic SSL/TLS client which can establish a transparent connection to ...

  10. Python框架学习之Flask中的Jinja2模板

    前面也提到过在Flask中最核心的两个组件是Werkzeug和Jinja2模板.其中Werkzeug在前一节已经详细说明了.现在这一节主要是来谈谈Jinja2模板. 一.为什么需要引入模板: 在进行软 ...