Redis事务和管道

Redis事务和管道

事务

一、概念

Redis事务是可以一次执行多个命令,本质是一组命令的集合。一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其他命令插入。

 

  • 单独的隔离操作:Redis事务仅仅是保证事务里的操作会被连续独占地执行,redis命令执行是单线程架构,在执行完事务内所有指令前是不可能再去同时执行其他客户端请求。

  • 没有隔离级别的概念:因为事务提交前任何指令都不会被实际执行,也就不存在“事务内的查询要看到事务里的更新,在事务外查询不能看到”这种问题了

  • 不保证原子性:Redis事务不保证原子性,也就是不保证所有指令同时成功或同时失败,只有决定 是否开始执行全部指令的能力,没有执行到一半进行回滚的能力。

  • 排他性:Redis会保证一个事务内的命令依次执行,而不会被其他命令插入

 

二、事务命令

redis的全部命令:

  • multi: 标记事务块的开始

  • exec:执行事务块内的所有命令

  • discard:取消事务,放弃事务块内的所有命令

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

  • unwatch:取消watch命令对所有key的监视

 

当一个事务正常执行时,通过multi开始事务,exec提交事务,事务块内的所有命令都正常执行

image-20240911105633950

 

当你不想要执行事务时,可以使用discard 取消事务

image-20240911105935550

 

如果在一个事务中出现了错误命令,那么使用exec提交事务时会报事务取消,其他的命令也不会执行

image-20240911110322468

 

如果一个事务中的命令没有语法上的错误,但是编译会报错,那么在该事务中除了有错误的命令,其他命令都会正确执行

image-20240911110549695

 

 

watch

redis使用watch来提供乐观锁,类似于CAS,乐观锁的策略是提交版本必须大于记录当前版本才能执行更新

正常监听:

image-20240911111200946

在没有其他进程修改的情况下,监听后可以正常修改成功

如果在监听后,提交事务之前,其他进程修改了监听的值,那么事务整体就失败了,会报 nil

image-20240911111853763

 

 

管道

为什么会有管道这个概念?

Redis是一种基于客户端-服务端模型以及请求/响应协议的tcp服务,一个请求会遵循以下步骤:

  1. 客户端向服务端发送命令分四步(发送命令-->命令排队-->命令执行-->返回结果),并监听Socket返回,通常以阻塞模式等待服务端响应

  2. 服务端处理命令,并将结果返回给客户端

上面两个步骤成为 Round Trip Time 简称RTT

如果同时需要执行大量的命令,那么就需要等待上一条命令应答后再执行,这中间不仅多了RTT,还频繁调用系统IO,发送网络请求,同时需要redis调用多次 read() 和 write() 系统方法,对系统有较大的影响,导致性能不好

 

管道(pipeline)可以一次性发送多条命令给服务端,服务端依次处理完毕后,通过一条响应一次性将结果返回,通过减少客户端与redis的通信次数来实现降低往返延时时间,管道的原理是队列,先进先出保证数据的顺序性

image-20240911134217023

 

最终管道的定义是:Pipeline是为了解决RTT往返时,仅仅是将命令打包一次性发送,对整个redis的执行不产生其他影响

 

如何用管道进行命令的批量执行?

首先把要执行的命令放到一个 txt文件中

在没有连接redis的终端中执行 cat cmd.txt | redis-cli -a 123456 --pipe

该命令用管道修饰符连接了起来,表示第一条命令作为参数 传到 第二条命令中。

也就是 txt文件中的命令在 redis中以管道的方式去执行

image-20240911140133289

 

Pipeline缓冲的指令只是会依次执行,不保证原子性,如果执行中指令发生异常,将会继续执行后续指令

使用pipeline组装的命令个数不能太多,不然数据量过大客户端阻塞的时间可能过久,同时服务端此时也被迫回复一个队列答复,占用很多内存

posted @ 2024-09-11 14:13  GrowthRoad  阅读(14)  评论(0编辑  收藏  举报