redis技术之旅四 redis的发布/订阅和事务
redis的发布/订阅
发布/订阅是一种有效的解耦了消息发布者和消息订阅者之间的耦合的一种消息通信模式,redis作为一种pub/sub server,在发布者和订阅者之间起到了一种消息路由的功能,订阅者可以通过subscribe和psubscribe命令向redis server订阅自己感兴趣的消息类型,redis将消息类型称为通道(channel)。当发布者通过publish命令向redis server发送特定类型的消息时。订阅该消息类型的全部client都会收到此消息。这里消息的传递是多对多的。一个client可以订阅多个 channel,也可以向多个channel发送消息。
redis支持的发布/订阅的命令
PSUBSCRIBE
订阅一个或者多个符合模式匹配的频道。
PUBLISH
将信息message发布到指定的频道。
PUBSUB
查看订阅与发布系统的内部命令,它由数个不同格式的子命令组成。支持的版本在>=2.8.0。
PUBSUB CHANNELS [pattern]
列出当前的活跃频道。
活跃频道指的是那些至少有一个订阅者的频道, 订阅模式的客户端不计算在内。
pattern 参数是可选的:
如果不给出 pattern 参数,那么列出订阅与发布系统中的所有活跃频道。
如果给出 pattern 参数,那么只列出和给定模式 pattern 相匹配的那些活跃频道。
复杂度: O(N) , N 为活跃频道的数量(对于长度较短的频道和模式来说,将进行模式匹配的复杂度视为常数)。
*******************************************************************************************
PUBSUB NUMSUB [channel-1 … channel-N]
返回给定频道的订阅者数量, 订阅模式的客户端不计算在内。
*******************************************************************************************
PUBSUB NUMPAT
返回订阅模式的数量。
注意, 这个命令返回的不是订阅模式的客户端的数量, 而是客户端订阅的所有模式的数量总和。
*******************************************************************************************
PUNSUBSCRIBE
PUNSUBSCRIBE [pattern [pattern …]]
指示客户端退订所有给定模式。
如果没有模式被指定,也即是,一个无参数的 PUNSUBSCRIBE 调用被执行,那么客户端使用 PSUBSCRIBE 命令订阅的所有模式都会被退订。在这种情况下,命令会返回一个信息,告知客户端所有被退订的模式。
SUBSCRIBE
SUBSCRIBE channel [channel …]
订阅给定的一个或多个频道的信息。
UNSUBSCRIBE
UNSUBSCRIBE [channel [channel …]]
指示客户端退订给定的频道。
如果没有频道被指定,也即是,一个无参数的 UNSUBSCRIBE 调用被执行,那么客户端使用 SUBSCRIBE 命令订阅的所有频道都会被退订。在这种情况下,命令会返回一个信息,告知客户端所有被退订的频道。
========================================================================================================================================================
redis的事务
redis的事务不同于关系型数据库MySQL/Oracle等中的事务,其对事务的支持比较简单,redis的事务只能保证在一个事务中的命令连续执行而不会被其他命令插入。redis是由单线程实现的,所以实现这样的功很简单,由multi发起一个事务,这是操作会进入一个事务上下文阶段,之后发起的命令不会马上执行,返回信息QUEUED,命令被放到队列里,直到执行exec命令,命令顺序执行,结束事务。
redis事务应用到的命令:
DISCARD
取消事务,放弃执行事务块内的所有命令。如果有正在被WATCH命令监视的KEY,discard会取消所有监视,等同于执行的unwatch命令。
EXEC
执行事务块中的所有命令,如果在事务块中涉及的key,有正在被watch命令监视的情况,那么只有在执行exec命令之前这个key没有被其他任何连接进行修改,事务才能执行成功,否则事务被打断,不会执行任何事务块中的操作。
MULTI
标记一个事务的开始,这个命令执行以后,事务块中的命令会被按顺序放置到队列里,最后由exec原子性的执行这些命令。
UNWATCH
取消watch命令对所有key的监控行为。
WATCH
监控一个或多个key,如果在事务执行之前,被监视的key被其他命令修改,那么事务被打断,不会被执行。
note1:
事务是单独的隔离操作,事务中的命令都会被序列化并按顺序执行,事务执行过程中不会被其他客户端发送的命令打断。
事务是原子性操作,事务中的命令要么全部执行,要么全不执行。
然而,还是会有些特殊的场景造成事务部分持久化的情况。如果redis服务器被管理员杀死或者硬件故障造成redis服务器宕机,而redis服务器采用的是AOF持久化策略来保障数据安全,服务器突然宕机可能会造成只有事务中的部分命令被持久化到硬盘,当redis server重启时会由于这个原因退出,并报出一个错误,这种情况需要对aof文件进行修复,redis-check-aof 程序可以修复这一问题,它会移除 AOF 文件中不完整事务的信息,确保服务器可以顺利启动。
note2:
redis的事务可能遇到两种错误:
事务在执行EXEC之前,如对的命令可能产生错误,如语法不对,参数不对等,对于这种错误,客户端以前的做法是检查命令入队的返回结果,如果返回入队失败,那么大部分的客户端会停止并取消这个事务。不过,redis从2.6.5开始,服务器对入队失败的命令进行记录,并在exec执行事务的时候拒绝知心并自动放弃这个事务。
事务在exec之后产生的错误,并没有任何的特殊处理,即使事务中的默写命令在exec之后产生了错误,事务中的其他命令正常执行。
note3:
redis的事务不支持回滚,redis只会因为错误的语法而失败,或者命令用在了错误的数据类型上,redis事务本身并不需要对这些操作进行回滚,这些错误应该在编程开发的过程中被发现,不应该出现的生产环境的代码里。因为不需要回滚的支持,redis内部可以保持简单快捷。