文章目录

  • 一 发布/订阅命令
  • 1.1 消息系统
  • 1.2 subscribe
  • 1.3 psubscribe
  • 1.4 publish
  • 1.5 unsubscribe
  • 1.6 punsubscribe
  • 1.7 pubsub
  • 1.7.1 pubsub channels
  • 1.7.2 pubsub numsub
  • 1.7.3 pubsub numpat
  • 二 Redis 事务
  • 2.1 Redis 事务特性
  • Redis 事务实现
  • 2.1.1 三个命令
  • 2.1.2 基本使用
  • 2.2. Redis 事务异常处理
  • 2.2.1 语法错误
  • 2.2.2 执行异常
  • 2.3 Redis 事务隔离机制
  • 2.3.1 需要事务隔离机制的原因
  • 2.3.2 隔离的实现
  • 2.3.3 隔离的实现原理


一 发布/订阅命令

1.1 消息系统

  • 发布/订阅(pub/sub),是一种消息通信模式:发布者【消息生产者】,生产和发送消息到存储系统;订阅者【消息消费者】,从存储系统接收和消费消息。这个存储系统可以是文件系统 FS、消息中间件 MQ、数据管理系统 DBMS,也可以是 Redis。 整个消息发布者、订阅者与存储系统称为消息系统。
  • 消息系统中的订阅者订阅了某类消息后,只要存储系统中存在该类消息,其就可不断的接收并消费这些消息。当存储系统中没有该消息后,订阅者的接收、消费阻塞。而当发布者将消息写入到存储系统后,会立即唤醒订阅者。当存储系统放满时,不同的发布者具有不同的处理方式:有的会阻塞发布者的发布,等待可用的存储空间;有的则会将多余的消息丢失。
  • 不同的消息系统消息的发布/订阅方式也是不同的。例如 RocketMQ、Kafka 等消息中间件构成的消息系统中,发布/订阅的消息都是以主题 Topic 分类的。而 Redis 构成的消息系统中,发布/订阅的消息都是以频道 Channel 分类的。

1.2 subscribe

  • 格式:SUBSCRIBE channel *channel …+
  • 功能:Redis 客户端通过一个 subscribe 命令可以同时订阅任意数量的频道。在输出了订阅主题后,命令处于阻塞状态,等待相关频道的消息。
  • django redis 发布订阅 redis订阅发布命令_django redis 发布订阅


  • django redis 发布订阅 redis订阅发布命令_django redis 发布订阅_02


1.3 psubscribe

  • 格式:PSUBSCRIBE pattern *pattern …+
  • 功能:订阅一个或多个符合给定模式的频道
  • 说明:这里的模式只能使用通配符 * 如,it* 可以匹配所有以 it 开头的频道,如it.news、it.blog、it.tweetsnews.*可以匹配所有以 news.开头的频道。
  • django redis 发布订阅 redis订阅发布命令_Redis_03


  • django redis 发布订阅 redis订阅发布命令_学习_04


1.4 publish

  • 格式:PUBLISH channel message
  • 功能:Redis 客户端通过一条 publish 命令可以发布一个频道的消息,返回值为接收到该消息的订阅者数量。
  • django redis 发布订阅 redis订阅发布命令_学习_05


1.5 unsubscribe

  • 格式:UNSUBSCRIBE *channel *channel …++
  • 功能:Redis 客户端退订指定的频道
  • 说明:如果没有频道被指定,会执行一个无参数的 unsubscribe 命令,客户端使用 SUBSCRIBE 命令订阅的所有频道都会被退订。在这种情况下,返回一个信息,告知客户端所有被退订的频道
  • django redis 发布订阅 redis订阅发布命令_学习_06


1.6 punsubscribe

  • 格式:PUNSUBSCRIBE *pattern *pattern …++
  • 功能:退订一个或多个符合给定模式的频道
  • 说明:这里的模式只能使用通配符 *。如果没有频道被指定,其效果与 SUBSCRIBE 命令相同,客户端将退订所有订阅的频道。
  • django redis 发布订阅 redis订阅发布命令_Redis_07


1.7 pubsub

  • 格式:PUBSUB <subcommand> [argument *argument …++
  • 功能:PUBSUB 是一个查看订阅与发布系统状态的内省命令集,它由数个不同格式的子命令组成

1.7.1 pubsub channels

  • 格式:PUBSUB CHANNELS [pattern]
  • 功能:列出当前所有的活跃频道。活跃频道指的是那些至少有一个订阅者的频道。
  • 说明:pattern 参数是可选的。如果不给出 pattern 参数,将会列出订阅/发布系统中的所有活跃频道。如果给出 pattern 参数,那么只列出和给定模式 pattern 相匹配的那些活跃频道。pattern 中只能使用通配符*。
  • django redis 发布订阅 redis订阅发布命令_Redis_08


1.7.2 pubsub numsub

  • 格式:PUBSUB NUMSUB [channel-1 … channel-N]
  • 功能:返回给定频道的订阅者数量。不给定任何频道则返回一个空列表。
  • django redis 发布订阅 redis订阅发布命令_django redis 发布订阅_09


1.7.3 pubsub numpat

  • 格式:PUBSUB NUMPAT
  • 功能:查询当前 Redis 所有客户端订阅的所有频道模式的数量总和
  • django redis 发布订阅 redis订阅发布命令_redis_10


二 Redis 事务
  • Redis 的事务的本质是一组命令的批处理。这组命令在执行过程中会被顺序地、一次性全部执行完毕,只要没有出现语法错误,这组命令在执行期间是不会被中断。

2.1 Redis 事务特性

  • Redis 的事务仅保证数据的一致性,不具有像 DBMS 一样的 ACID 特性。
  • 不具备原子性:这组命令中的某些命令的执行失败不会影响其它命令的执行,不会引发回滚。
  • 没有复杂的隔离级别:这组命令通过乐观锁机制实现了简单的隔离性。
  • 与事务无关:这组命令的执行结果是被写入到内存的,是否持久取决于 Redis 的持久化策略

Redis 事务实现

2.1.1 三个命令

  • Redis 事务通过三个命令进行控制。
    • muti:开启事务
    • exec:执行事务
    • discard:取消事务

2.1.2 基本使用

  • 下面是定义并执行事务的用法:事务执行后,再访问事务中定义的变量,其值是修改过后。
  • django redis 发布订阅 redis订阅发布命令_django redis 发布订阅_11


  • 下面是定义但取消事务的举例:事务取消后,事务中的命令是没有执行的
  • django redis 发布订阅 redis订阅发布命令_django redis 发布订阅_12


2.2. Redis 事务异常处理

2.2.1 语法错误

  • 当事务中的命令出现语法错误时,整个事务在 exec 执行时会被取消
  • django redis 发布订阅 redis订阅发布命令_redis_13


2.2.2 执行异常

  • 如果事务中的命令没有语法错误,但在执行过程中出现异常,该异常不会影响其它命令的执行
  • django redis 发布订阅 redis订阅发布命令_Redis_14


  • django redis 发布订阅 redis订阅发布命令_django redis 发布订阅_15


2.3 Redis 事务隔离机制

2.3.1 需要事务隔离机制的原因

  • 在并发场景下可能会出现多个客户端对同一个数据进行修改的情况,造成数据不一致的情况!
    • 如:有两个客户端 C 左与 C 右,C 左需要申请 40 个资源,C 右需要申请 30 个资源。它们首先查看了当前拥有的资源数量,即 resources 的值为50,都感觉资源数量可以满足自己的需求,于是修改资源数量,以占有资源。但结果却是资源出现了“超卖”情况。
    • django redis 发布订阅 redis订阅发布命令_Redis_16


  • Redis 事务通过乐观锁机制实现了多线程下的执行隔离

2.3.2 隔离的实现

  • Redis 通过 watch 命令再配合事务实现了多线程下的执行隔离
  • django redis 发布订阅 redis订阅发布命令_Redis_17


  • 以上两个客户端执行的时间顺序为:
  • django redis 发布订阅 redis订阅发布命令_学习_18


2.3.3 隔离的实现原理

  1. 当某一客户端对 key 执行了 watch 后,系统就会为该 key 添加一个 version 乐观锁,并初始化 version。例如初值为 1.0。
  2. 此后客户端 C 左将对该 key 的修改语句写入到了事务命令队列中,虽未执行,但其将该key 的 value 值与 version 进行了读取并保存到了当前客户端缓存。此时读取并保存的是version 的初值 1.0。
  3. 此后客户端 C 右对该 key 的值进行了修改,这个修改不仅修改了 key 的 value 本身,同时也增加了 version 的值,例如使其 version 变为了 2.0,并将该 version 记录到了该 key信息中。
  4. 此后客户端 C 左执行 exec,开始执行事务中的命令。不过,其在执行到对该 key 进行修改的命令时,该命令首先对当前客户端缓存中保存的 version 值与当前 key 信息中的version 值。如果缓存 version 小于 key 的 version,则说明客户端缓存的 key 的 value 已经过时,该写操作如果执行可能会破坏数据的一致性。所以该写操作不执行
  5. django redis 发布订阅 redis订阅发布命令_redis_19