【Redis7学习日记】—— 事务、管道、发布订阅

一、事务

1.1 Redis 事务是什么

  • 首先,我们要了解传统数据库的事务代表什么?

    • 一次与数据库的连接会话当中,所有执行的 SQL,要么一起成功,要么一起失败【例如:银行转账】
  • 那么,我们 Redis 事务与 传统数据库的事务有什么不同吗?【以下是Redis事务的特性】
    【Redis7学习日记】—— 事务、管道、发布订阅_第1张图片

  • 接下来,我们再说说 Redis 事务是什么?

    • 可以一次执行多个命令,本质是一组命令的集合,一个事务中所有命令都会被序列化,按顺序的串行化执行而不会被其他命令插入【不需加塞】
      • 换句话说:就是一个队列中一次性、顺序性、排他性的执行一系列命令

1.2 Redis 事务怎么用

  • 首先,我们来看一下事务相关的命令
    【Redis7学习日记】—— 事务、管道、发布订阅_第2张图片

  • 对于事务的使用,阳哥为我们分为五种情况:

    • 正常执行
    • 放弃事务
    • 全体连坐
    • 冤头债主
    • watch 监控
  • 接下来我们对这几部分展开叙述

1️⃣ 正常执行:

  • 通过 multi 指令开启事务,通过 exec 指令开始执行事务
    【Redis7学习日记】—— 事务、管道、发布订阅_第3张图片

2️⃣ 放弃事务:

  • 在事务开始前,通过 discard 指令可以放弃事务,事务中的指令全部不会执行
    【Redis7学习日记】—— 事务、管道、发布订阅_第4张图片

3️⃣ 全体连坐:

  • 在事务执行前,如果存在语句语法有错误,那么使用 exec 指令执行事务的时候,事务内的指令都不会执行

【Redis7学习日记】—— 事务、管道、发布订阅_第5张图片

4️⃣ 冤头债主:

  • 就是在事务执行前没检查出来错误,在通过 exec 命令执行事务后,发现了错误,这样争取的指令都会执行,错误的指令不会执行
  • 因为 Redis 不提供事务回滚的功能,开发者必须在事务执行出错后,自行恢复数据库状态
  • 这里就体现出与传统事务的差异了,指令集合中的语句不是同时成功或失败

【Redis7学习日记】—— 事务、管道、发布订阅_第6张图片

5️⃣ watch 监控:

  • 在介绍这部分之前,我们需要知道什么是乐观锁、悲观锁?

    • 悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。
    • 乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据。
      • 乐观锁策略:提交版本必须 大于 记录当前版本才能执行更新
  • Redis 使用 Watch 来实现乐观锁定类似 CASCheck And Set
    【Redis7学习日记】—— 事务、管道、发布订阅_第7张图片

使用 check-and-set WATCH 的乐观锁定用于为Redis事务提供一个check-and-set (CAS)行为。WATCH键被监视,以检测它们的变化。如果在执行EXEc命令之前至少修改了一个被监视的键,则整个事务将中止,EXEc将返回Null应答,通知事务失败。

  • 我们来演示一下这个 watch 监控的使用:
    • 初始化 k1balance 两个 key,先通过 watch 监控 key,在通过 multi 开启事务,保证两个 key 的变动在一个事务内
      【Redis7学习日记】—— 事务、管道、发布订阅_第8张图片

    • 监测的 key 存在数据篡改行为
      【Redis7学习日记】—— 事务、管道、发布订阅_第9张图片

  • watch命令是一种乐观锁的实现,Redis在修改的时候会检测数据是否被更改,如果更改了,则执行失败,第一个窗口蓝色框第5步执行结果返回为空,也就是相当于是失败
  • Redis 事务的 unwatch 命令用于取消 WATCH 命令对所有 key 的监视
    【Redis7学习日记】—— 事务、管道、发布订阅_第10张图片
  • 小结:
    • Redis 开始执行事务(EXEC),那么之前加的所有的锁都会被释放
    • 当客户端连接丢失时(比如退出连接),所有的东西都会取消监视

1.3 Redis 事务总结

  • 开启:通过 multi 指令开启一个事务
  • 入队:将多个命令入队到事务中,接到这些命令并不会立即执行,而是放到等待执行的事务队列中
  • 执行:通过 exec 命令触发事务

二、管道

2.1 背景

  • 首先,我们先了解一下为什么会产生管道这种机制:
    • Redis 是一种基于客户端-服务端模型以及请求/响应协议的TCP服务。一个请求会遵循以下步骤:
      • 1 客户端向服务端发送命令分四步(发送命令→命令排队→命令执行→返回结果),并监听Socket返回,通常以阻塞模式等待服务端响应。
      • 2 服务端处理命令,并将结果返回给客户端。

【Redis7学习日记】—— 事务、管道、发布订阅_第11张图片

  • 如果同时需要执行大量的命令,那么就要等待上一条命令应答后再执行,这中间不仅仅多了RTT(Round Time Trip),而且还频繁调用系统IO,发送网络请求,同时需要redis调用多次read()和write()系统方法,系统方法会将数据从用户态转移到内核态,这样就会对进程上下文有比较大的影响了,性能不太好

2.2 管道定义

  • 为了解决上面的这个问题,我们引出管道的概念:
    • 管道(pipeline)可以一次性发送多条命令给服务端,服务端依次处理完完毕后,通过一条响应一次性将结果返回,通过减少客户端与redis的通信次数来实现降低往返延时时间
    • pipeline实现的原理是队列,先进先出特性就保证数据的顺序性

【Redis7学习日记】—— 事务、管道、发布订阅_第12张图片

  • 管道的定义Pipeline是为了解决RTT往返回时,仅仅是将命令打包一次性发送对整个Redis的执行不造成其它任何影响
    • 批处理命令变种优化措施,类似Redis的原生批命令(mgetmset)

【Redis7学习日记】—— 事务、管道、发布订阅_第13张图片

2.3 总结

  • Pipeline与原生批量命令对比:
    • 原生批命令是原子性的,pipeline 是非原子性的
    • 原生批量命令一次只能执行一种命令,pipeline 支持批量执行不同命令
    • 原生批命令是服务端实现,pipeline 需要服务端和客户端共同实现
  • Pipeline与事务对比:
    • 事务具有原子性,管道不具有原子性
    • 管道一次性将多条命令发送到服务器,事务是一条一条的发,事务只有在执行 exec 命令后才会执行,管道不会
    • 执行事务时会阻塞其他命令,执行管道的时候不会
  • 使用 Pipeline 的注意事项:
    • 管道的缓冲中的指令只会依次执行,不保证原子性,如果执行中指令发生了异常,将会继续执行后续的指令
    • 使用pipeline组装的命令个数不能太多,不然数据量过大客户端阻塞的时间可能过久,同时服务端比时也被迫回复一个队列答复,占用很多内存

三、发布订阅

  • 是一种消息通信模式,发送者(publish)发送消息,订阅者(subscribe)接收消息,实现进程间的消息传递
  • Redis 可以实现消息中间件的功能,通过发布订阅实现消息的引导和分流

3.1 功能总结

  • Redis 客户端可以订阅任意数量的频道【类似微信公众号】
    【Redis7学习日记】—— 事务、管道、发布订阅_第14张图片
  • 当有新消息通过 publish 发送给 channel1 时,可以参考我们下面的这张图
    【Redis7学习日记】—— 事务、管道、发布订阅_第15张图片
  • 发布/订阅其实是一个轻量的队列,只不过数据不会被持久化,一般用来处理实时性较高的异步消息
    【Redis7学习日记】—— 事务、管道、发布订阅_第16张图片

3.2 常用命令

  • 通过subscribe channel [channel ..]命令可以订阅一个或多个频道的信息
    • 推荐先订阅再发布,因为订阅成功前发布的信息是收不到的
    • 订阅的客户端一次可以接收由三个参数组成的消息
      • 消息的种类
      • 始发频道
      • 消息的内容
        在这里插入图片描述
  • 通过publish channel message 命令可以发送消息到指定的频道
  • 通过 psubscribe pattern [pattern...] 命令可以按照模式批量订阅,订阅一个或多个符合给定模式(支持*号?号之类的)的频道
  • 通过 pubsub subcommand [argument [argument...]] 命令可以查看订阅与发布系统状态
    • 通过 pubsub channels 命令可以查看由活跃频道组成的列表
      在这里插入图片描述

    • 通过 pubsub numsub [channel [channel...]] 命令可以查看某个频道有几个订阅者
      在这里插入图片描述

    • 通过 pubsub numpat 命令只会统计通过 psubscribe 命令执行的,返回客户端订阅的唯一模式的数量
      【Redis7学习日记】—— 事务、管道、发布订阅_第17张图片

  • 通过 unsubscribe [channel [channel...]] 命令可以取消订阅某个频道
  • 通过 punsubscribe [pattern [pattern ...]] 命令可以退订所有给定模式的频道

3.3 总结

  • Redis可以实现消息中间件MQ的功能,通过发布订阅实现消息的引导和分流 【专业人做专业事 >> 不推荐使用】
  • 说一下 Pub/Sub 的缺点:
    • 发布的消息在Rds系统中不能持久化,因此,必须先执行订阅,再等待消息发布。如果先发布了消息,那么该消息由于没有订阅者,消息将被直接丢弃
    • 消息只管发送对于发布者而言消息是即发即失的,不管接收,也没有ACK机制,无法保证消息的消费成功
    • 以上的缺点导致RedisPub/Sub模式就像个小玩具,在生产环境中几乎无用武之地,为此 Redis5.0版本新增了Stream数据结构,不但支持多播,还支持数据持久化,相比Pub/Sub更加的强大

你可能感兴趣的:(Redis,数据库,redis,事务,管道,发布订阅)