2023-06-09:什么是 Redis 事务?原理是什么?
2023-06-09:什么是 Redis 事务?原理是什么?
答案 2023-06-09:
Redis 中的事务是以一组命令的形式出现的,这些命令被认为是最小的执行单位。事务可以保证在一个单独独立的隔离操作中执行所有命令,而且所有命令都会按照指定的顺序经过序列化后被执行。在服务端执行事务的过程中,不受其他客户端发送给 Redis 的命令请求的干扰影响。
Redis 事务的注意点有哪些?
Redis 事务的使用需要注意以下几点:
1.Redis 事务不支持回滚,不能像 MySQL 的事务那样可以选择性地输出。一旦命令提交给 Redis,就会被执行,无法扔回到事务的起点。
2.Redis 事务是原子执行的,要么全部执行成功,要么放弃执行。如果其中一个命令失败,则整个事务都会失败,但不会因为其中一个命令失败而导致其他命令的执行效果不确定。
3.执行事务期间,Redis 服务器不会中断执行,也不会被其他客户机的请求干扰,这保证了事务操作期间的隔离性和原子性。
4.事务中的命令都是串行执行的,并且事务会尽量缩短命令合并的时间。如果有多个客户端同时访问同一个命令,会根据请求的时间顺序进行处理,避免了竞争和死锁。
Redis 事务为什么不支持回滚?
Redis 事务执行期间不支持回滚的主要原因是为了避免增加复杂的实现逻辑和增加系统负担。 Redis 只能通过在事务提交前执行所有命令来保证原子性的特性。如果 Redis 支持回滚,则必须存储事务执行前的状态,并在回滚后重置状态,这样会增加显著的存储和计算负担。
当命令执行期间发生语法错误等问题,Redis 会在执行失败时报错,开发人员可以通过编写代码来处理这些错误。但是出现严重问题时,如网络故障或硬件问题等,Redis 仍然会执行已经提交的事务命令,此时数据可能会出现严重不一致,需要开发人员自行修复。
总之,虽然没有回滚功能,但是 Redis 事务仍然是非常有用和实用的功能,能够提供高效、快速和可靠的多命令操作。开发人员需谨慎处理错误处理方式和保证数据一致性,以获得最佳实践的体验。
事务
事务是一组操作或动作的集合,这些操作要么全部执行,要么全部不执行。在执行事务期间,可以保证隔离性和原子性,即在同一事务中执行的操作相互独立,不受其他事务的干扰。如果其中一个操作发生错误,则仅回滚该事务,而不影响其他事务的执行结果。事务通常用于需要一系列操作来完成的任务,例如向数据库中插入多个数据,或将多个操作组合成一个原子操作。
以社交网站上用户 A 关注用户 B 为例,这个动作需要在用户 A 的关注表中添加用户 B,并在用户 B 的粉丝表中添加用户 A。将这两个操作组合成事务,可以确保在同一个事务中执行,要么全部执行,要么全部不执行。这样可以避免出现数据不一致的情况,确保关注关系的正确性。使用事务可以将多个数据库操作组合成一个原子操作,保证数据的一致性。
Redis 提供了简单的事务功能,以 multi 命令开始事务,并在调用 exec 命令结束事务。将需要一起执行的命令放在 multi 和 exec 之间,Redis 会将这些命令作为一个原子操作来处理,要么全部执行,要么全部不执行。如果在事务执行期间需要取消已经执行的命令,可以使用 discard 命令回滚整个事务。利用 Redis 的事务功能,可以执行多个命令并确保它们在同一个事务中执行,避免了因单个命令执行失败而导致的数据不一致问题。
一个客户端
另外一个客户端
在事务没有提交的时查询(查不到数据)
在事务提交后查询(可以查到数据)
可以看到 sadd 命令此时的返回结果是 QUEUED,代表命令并没有真正执行,而是暂时保存在 Redis 中的一个缓存队列(所以 discard 也只是丢弃这个缓存队列中的未执行命令,并不会回滚已经操作过的数据,这一点要和关系型数据库的 Rollback 操作区分开)。
只有当 exec 执行后,用户 A 关注用户 B 的行为才算完成,如下所示 exec 返回的两个结果对应 sadd 命令。
但是要注意 Redis 的事务功能很弱。在事务回滚机制上,Redis 只能对基本的语法错误进行判断。
如果事务中的命令出现错误,Redis 的处理机制也不尽相同。
1、语法命令错误
例如下面操作错将 set 写成了 sett,属于语法错误,会造成整个事务无法执行,事务内的操作都没有执行:
2、运行时错误
例如:事务内第一个命令简单的设置一个 string 类型,第二个对这个 key 进行 sadd 命令,这种就是运行时命令错误,因为语法是正确的:
可以看到 Redis 并不支持回滚功能,第一个 set 命令已经执行成功,开发人员需要自己修复这类问题。
Redis 的事务原理
Redis 的事务是在服务器端实现的,当用户执行 MULTI 命令时,服务器将对应的客户端对象设置为一个专门的状态,此状态下所有后续用户所执行的查询命令都不会被立即执行,而是被保存在一个事务队列中,直到用户执行 EXEC 命令为止。在执行 EXEC 命令前或在事务途中,客户端可以随时调用 DISCARD 命令来取消事务。当用户执行 EXEC 命令时,服务器会将该客户端对象中缓存的命令按照它们提交的顺序依次执行,并将执行结果返回给客户端。使用 Redis 事务可以将一系列命令作为单个原子操作执行,从而保证了操作的一致性。
版权声明: 本文为 InfoQ 作者【福大大架构师每日一题】的原创文章。
原文链接:【http://xie.infoq.cn/article/ed17d42f5ac2e5cf9e354fcf7】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论