redis发布订阅及事务

redis发布订阅

例:订阅者:

redis 127.0.0.1:6379> SUBSCRIBE redisChat

Reading messages... (press Ctrl-C to quit)

1) "subscribe"

2) "redisChat"

3) (integer) 1

发布者:

redis 127.0.0.1:6379> PUBLISH redisChat "Redis is a great caching technique"

(integer) 1

redis 127.0.0.1:6379> PUBLISH redisChat "Learn redis by runoob.com"

(integer) 1

# 订阅者的客户端会显示如下消息

1) "message"

2) "redisChat"

3) "Redis is a great caching technique"

1) "message"

2) "redisChat"

3) "Learn redis by runoob.com"

要求订阅china为前缀的所有频道:

PSUBSCRIBE pattern [pattern ...]

订阅一个或多个符合给定模式的频道。

每个模式以 * 作为匹配符,比如 it* 匹配所有以 it 开头的频道( it.news 、 it.blog 、 it.tweets 等等), news.* 匹配所有以 news. 开头的频道( news.it 、 news.global.today 等等),诸如此类。

退订:

使用 UNSUBSCRIBE 命令可以退订指定的频道, 这个命令执行的是订阅的反操作: 它从 pubsub_channels 字典的给定频道(键)中, 删除关于当前客户端的信息, 这样被退订频道的信息就不会再发送给这个客户端。

redis事务

以下是一个事务的例子, 它先以 MULTI 开始一个事务, 然后将多个命令入队到事务中, 最后由 EXEC 命令触发事务, 一并执行事务中的所有命令:

redis 127.0.0.1:6379> MULTI

OK

redis 127.0.0.1:6379> SET book-name "Mastering C++ in 21 days"

QUEUED

redis 127.0.0.1:6379> GET book-name

QUEUED

redis 127.0.0.1:6379> SADD tag "C++" "Programming" "Mastering Series"

QUEUED

redis 127.0.0.1:6379> SMEMBERS tag

QUEUED

redis 127.0.0.1:6379> EXEC

1) OK

2) "Mastering C++ in 21 days"

3) (integer) 3

4) 1) "Mastering Series"

   2) "C++"

   3) "Programming"

单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。

事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。

相关命令:

discard              取消事务,放弃执行事务块内的所有命令。

watch key [key ...]                  监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。

unwatch             取消 WATCH 命令对所有 key 的监视。

事务内部的错误:

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

 

一个命令可能会在被放入队列时失败。因此,事务有可能在调用EXEC命令之前就发生错误。例如,这个命令可能会有语法错误(参数的数量错误、命令名称错误,等等),或者可能会有某些临界条件(例如:如果使用maxmemory指令,为Redis服务器配置内存限制,那么就可能会有内存溢出条件)。 

在调用EXEC命令之后,事务中的某个命令可能会执行失败。例如,我们对某个键执行了错误类型的操作(例如,对一个字符串(String)类型的键执行列表(List)类型的操作)。

可以使用Redis客户端检测第一种类型的错误,服务器会记住事务积累命令期间发生的错误。然后,Redis会拒绝执行这个事务,在运行EXEC命令之后,便会返回一个错误消息。最后,Redis会自动丢弃这个事务。

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

在事务运行期间,虽然Redis命令可能会执行失败,但是Redis仍然会执行事务中余下的其他命令,而不会执行回滚操作。

 

只有当被调用的Redis命令有语法错误时,这条命令才会执行失败(在将这个命令放入事务队列期间,Redis能够发现此类问题),或者对某个键执行不符合其数据类型的操作:实际上,这就意味着只有程序错误才会导致Redis命令执行失败,这种错误很有可能在程序开发期间发现,一般很少在生产环境发现。 

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变量的结果,那么事务将会运行失败。

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值