Redis事务/管道

104 阅读6分钟

Redis事务/管道

一、事务

一、概念

Redis 事务可以一次执行多个命令, 并且带有以下两个重要的保证:

  • 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
  • 事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。

一个事务从开始到执行会经历以下三个阶段:

  • 开始事务。
  • 命令入队。
  • 执行事务。

简单理解为:

你可以把一堆需要一起完成的事情放进这个魔法盒子里,然后一起执行。要么所有的事情都成功完成,要么就什么都不做,就像一把开关,要么全开,要么全关。

Redis事务的作用就是让你可以把一组操作像一块做,要么都成功,要么都不做,中间不会有人插一脚。这样保证了数据处理的可靠性,就像魔法一样神奇

二、与数据库事务的区别

特性Redis事务数据库事务
支持的操作读写命令,以及特定的事务控制命令增、删、改、查等数据库操作
原子性仅保证在单个键上的原子性是(保证一组操作要么全部成功,要么全部失败)
隔离性没有隔离级别的概念,在事务提交之前,所有的指令都不会被实际的执行。根据隔离级别(如读未提交、读已提交等)
一致性保证了单个键上的一致性是(保证事务结束后数据库的状态是一致的)
持久性是(可以通过将数据写入磁盘来保证持久性)是(事务结束时对数据库的更改会被永久保存)
并发访问时的行为WATCH命令可以用于监视一个或多个键,确保在事务执行期间被其他客户端修改的情况下,事务会被取消根据隔离级别,可能会出现脏读、不可重复读、幻读等问题
主要应用场景缓存、计数器、队列等常用于管理复杂的数据操作,如用户注册、订单支付等

三、常见的命令

下面是Redis事务的相关命令:

命令描述
MULTI开启事务,用于开始一个事务块。
EXEC执行所有事务块内的命令。
DISCARD取消事务,放弃执行事务块内的所有命令。
WATCH监视一个或多个键,如果在事务执行前这些键被其他命令改动,事务将会被打断。
UNWATCH取消对所有键的监视。
MULTI/EXEC以原子性方式执行多个命令,将它们包裹在一个事务中。

具体的操作流程:

1、开启: 以MULTI开始一个事务块。

2、入队:将多个命令入队到事务块中。入队的命令不会立即执行。而是放到等待执行的的队列中

2、执行:最后通过EXEC命令来触发事务的执行

1、正常执行

2、放弃事务

3、事务块命令编译失败

二、管道

一、概念

Redis是一种基于客户端-服务端模型以及请求/响应协议的TCP服务。这意味着通常情况下一个请求会遵循以下步骤:

  • 客户端向服务端发送一个查询请求,并监听Socket返回,通常是以阻塞模式,等待服务端响应。
  • 服务端处理命令,并将结果返回给客户端。

上述两步称为:Round Trip Time (简称RTT,数据包往返于两端的时间)

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

Redis 管道技术(Pipeline)可以在服务端未响应时,客户端可以继续向服务端发送请求,并最终一次性读取所有服务端的响应。

二、管道与原生批命令对比

方面Redis管道技术原生批命令
通信次数大幅减少,一次发送多个命令,一次性获取多个结果。每个命令都需要单独的通信,然后分别获取结果。
性能提升显著,特别适用于批量处理多个命令的场景。可以提升性能,但不如管道技术明显。
并发性可能会阻塞其他客户端,因为Redis是单线程的。不会阻塞其他客户端,可以并发执行多个命令。
原子性每个命令在管道内部是原子性的,但管道外的原子性需要开发者自行保证。原生批命令也是原子性的,要么全部执行,要么一个都不执行。
适用场景需要同时处理多个命令的场景,如批量获取、批量写入等。适用于一次性执行多个命令,但没有特别需要一起执行的场景。
对客户端的编程复杂性需要使用管道相关的API,编程稍微复杂一些。使用循环或其他方式实现批处理,相对简单。

总的来说,Redis管道技术可以显著减少通信开销,提升性能,特别适用于需要批量处理多个命令的场景。然而,需要注意管道可能会阻塞其他客户端,因此在使用时需要谨慎考虑。原生批命令也能实现类似的效果,但性能提升可能不如管道明显。选择使用哪种方式取决于具体的业务场景和需求。

三、注意事项

  1. 性能提升可能会受限:虽然Redis管道可以显著减少通信开销,但性能提升可能受到Redis服务器的性能限制。如果Redis服务器的性能有限,管道技术可能无法发挥其最大的优势。
  2. 阻塞其他客户端:在管道执行期间,其他客户端可能会被阻塞,因为Redis是单线程的。因此,在使用管道时,需要考虑到可能会对其他客户端的操作产生影响。
  3. 处理错误响应:在使用管道时,需要注意处理每个命令的响应结果。如果在管道中某个命令执行失败,需要根据具体情况进行处理。
  4. 保证原子性:管道内部的每个命令是原子性的,但管道外的原子性需要开发者自行保证。如果需要保证一组命令的原子性,需要使用Redis事务。
  5. 不适用于所有场景:管道技术适用于需要同时处理多个命令的场景,如批量获取、批量写入等。但并不是所有情况下都适合使用管道,需要根据具体业务需求进行评估。
  6. 错误处理:在使用管道时,需要注意处理可能发生的错误情况。可以使用try-catch语句块来捕获并处理异常情况。