Redis 事务特性、原理、具体命令操作全方位诠释 —— 零基础可学习

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 本文全面阐述了Redis事务的特性、原理、具体命令操作,指出Redis事务具有原子性但不保证一致性、持久性和隔离性,并解释了Redis事务的适用场景和WATCH命令的乐观锁机制。

1、复习 MySQl 事务的特性

  • 原子性:事务是原子的,它被视为一个不可分割的工作单元。事务中的所有操作要么全部执行成功,要么全部失败回滚,不存在中途状态。原子性确保了数据库的一致性。
  • 一致性:事务执行之前,和之后,数据都不能离谱,维护数据库的一致性,和原子性密切相关
  • 持久性:一旦事务提交,其结果应该是永久性的(存硬盘),即使在系统发生故障的情况下也不会丢失。数据库的持久性保证了数据的长期存储。
  • 隔离性:多个事务可以并发执行,但其结果必须与按某种顺序串行执行的结果一致。隔离性确保一个事务的执行不会被其他事务干扰,通过隔离性可以避免一些并发引起的问题,如脏读(dirty read)、不可重复读(non-repeatable read)和幻读(phantom read)

一致性举例:在一个mysql的事务操作中,事务要么全部执行成功,要么全部失败回滚,不可以有的成功,有的失败,以维护数据库的一致性

2、Redis 事务特性

2.1、原子性(有没有存在争议)

  • 最原本的含义,是把多个操作打包到一起,要么全部执行,要么全部不执行
  • Redis 确实做到了上述的含义,但如果事务中若干个操作,存在有失败的,那就失败吧,不会有回滚操作
  • 相比来说MySQL这里的原子性,走得更远,也是把多个操作打包到一起,要么全都执行成功,要么全都不执行
  • 如果mysql的事务中有操作执行失败,则进行回滚!把中间已经执行的操作,全都回退了
  • 不得不说,MySQL在这方面成为了“标兵”,提高了“原子性”的门槛
  • 这就使人们谈到原子性的时候,更多的是想到的MySQL这种带有回滚的原子性

网上看到,有的人说,redis事务有原子性,有的说没有原子性

  • 说有原子性的原因是因为:它确实满足了原子性最基本的含义,将任务打包执行(也只是打包一起执行了)
  • 说没有原子性的原因是因为:它没有满足mysql那种事务原子性的操作,他们认为原子性应该是打包一起执行+带有回滚,而明显,redis只是打包一起执行,失败不回滚,这种操作不被他们认为是原子性

2.2、一致性、持久性、隔离性(没有)

不具备一致性:redis没有约束,也没有回滚机制,事务执行过程中如果某个修改操作出现失败,就可能引起不一致的情况

不具备一致性:redis本身就是内存数据库,数据是存储在内存中的。虽然redis也有持久化机制,但是这里的持久化机制,和事务没有什么直接关系

不具备隔离性:redis是一个单线程模型的服务器程序,所有的请求/事务,都是“串行”执行的(多线程涉及隔离性,redis单线程,和隔离性扯不到一起)

Redis 的事务,主要的意义,就是为了“打包”,避免其他客户端的命令,插队插到中间

3、redis事务举生活例子

  • 我生日这一天,我和媳妇约好了,晚上出去吃烧烤
  • 但是呢,女人嘛,出门是一件麻烦的事情 (化妆...)
  • 我就先到了烧烤店,点了牛肉串若干,羊肉串若干,五花肉若干,点完之后,我告诉服务员,“我这人还没齐,你先把单下着,但是先不着急烤”
  • 过了一会,我媳妇到了,她又加了一盘烤韭菜,又加了两个烤腰子
  • 随后,我告诉服务员:开始考吧!
  • 此时,先点的这些肉 和 后点的韭菜、腰子 是一起烤的
  • 这两组中间,是没有被插队的
  • 这个不插队,不是先抢占位置,而是先让出位置

其实,这就是redis事务一种典型体现,将若干命令打包到一起执行,而且redis事务的执行逻辑也是不立即执行(不抢占位置),下发执行该事务命令后,redis会把当前正在做的事情(比如已经在执行一个事务,会把这个事务做完)做完后,再执行这个事务

4、redis事务的实现方式

  • redis中实现事务,是引入了队列(每个客户端都有一个)
  • 开启事务的时候,此时客户端输入的命令,就会发给服务器并且进入这个队列中(而不是立即执行)
  • 当遇到了“执行事务”命令的时候,此时就会把队列中的这些任务都按照顺序依次执行
  • 这些任务都是在redis主线程中完成的,主线程会把事务中的操作都执行完,再处理别的客户端

5、redis的事务为什么搞得这么简单? 为什么不涉及成和MySQL一样强大呢

  • MySQL的事务,在背后付出了很大的代价
  • 空间上,要花费更多的时间来存储更多的数据
  • 时间上,也要有更大的执行开销
  • 正是因为MySQL上述的问题,才有了redis上场的机会
  • redis想要效率高,必须舍弃掉一些功能

总结: 鱼和熊掌不可兼得!

6、什么时候需要使用到redis的事务呢?以及redis事务的相关逻辑

如果我们把多个操作打包进行,使用事务是比较合适的

比如当我们秒杀商品时,商家放货了5000台,实际如果让5001个人下单成功,就是超卖了

在秒杀商品等情况下就需要redis、的事务了

把每个用户点击购买直到完全下单成功并且商家货物减少这一整个操作合成一个事务进行执行

以前在多线程中,是通过加锁的方式,来避免“插队”的,在redis中就直接使用事务,即可!

逻辑如下:

7、redis事务的具体命令操作

事务三大基本命令 —— 开启、执行、放弃

  • 开启事务 —— MULTI
  • 执行事务 —— EXEC
  • 放弃当前事务 —— DISCARD
  • 开启事务(multi)后,可以编写事务中的具体操作,这些操作不会被执行,但会加入到这个事务中,待执行命令EXEC后 ,redis会着手执行该事务,即依次执行该事务中的所有命令语句
  • discard表示放弃当前事务,相当于刚才没有进行对事务的操作

redis中的 lua 脚本,也能起到类似于事务的效果

官方网站上说,事务这里的任何能实现的效果,都可以使用 lua 脚本代替

代码举例:

  • 当开启事务,并且给服务器发送若干个命令之后,此时服务器重启,此时的这个事务咋办?
  • 此时的效果就等同于discard

8、WATCH —— 监控key

watch 监控某个key是否在事务执行之前,发生了改变

刚才的场景中,就可以使用watch命令来监控这个key

看看这个key在事务的 multi 和 exec 之间,set key 之后,是否在外部被其他客户端修改了

watch开启后,在 NULTI 和 exec间另一个 redis客户端对 key进行了修改,此时提交事务,事务中对 key的操作就不会真正被执行!

watch 的实现原理,类似 “乐观锁”

watch 可以监测一个 key,也可以监测多个 key

乐观锁、悲观锁不是指某个具体的锁,而是指的是某一类锁的特性

  • 乐观锁:加锁之前,就有一个心理预期,预期接下来锁冲突的概率比较低
  • 悲观锁:加锁之前,也有一个心理预期,接下来锁冲突的概率比较高

锁冲突指的是两个线程针对同一个锁加锁,一个能加锁成功,另一个就得阻塞等待

watch的原理:

  • 当执行 watch key 的时候
  • redis就会给这个key安排一个版本号
  • 版本号可以理解成一个“整数”
  • 每次在修改的时候,版本号就会“变大”
  • 然后在执行 事务 中命令的时候
  • 就会做出判定
  • 判定这个key的版本号,和最初 watch 的时候
  • 记录的版本号是否一致!!!
  • 如果一致,说明当前key在事务开启到最终执行这个过程中,没有别的客户端修改,于是才能真正执行这个事务
  • 如果不一致,说明key在其他客户端中改过了,因此此处就直接丢弃事务中的操作,exec返回nil(空)

逻辑图及相关解释如下:

简单解释CAS和ABA,若不理解可以私信博主或者自行查询:

  • Redis Watch 命令给事务提供check-and-set (CAS) 机制。被Watch的Key被持续监控,如果key在Exec命令执行前有改变,那么整个事务被取消。
  • ABA问题是CAS机制的缺陷,大概意思是 A(旧值)-->B(新值)-->A(新值) cas乐观锁会认为A没被修改。 但是redis的watch在这种情况下,依然会提示watch key被修改,事务失败。

    🧸欢迎您于百忙之中阅读这篇博客,📜希望这篇博客给您带来了一些帮助,祝您生活愉快!

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
目录
相关文章
|
10天前
|
监控 NoSQL 关系型数据库
Redis:事务(Transactions)
Redis事务支持将多个命令打包执行,但与MySQL不同,它不保证原子性、一致性、持久性和隔离性。Redis事务的核心在于“打包”命令,避免其他客户端插队,通过MULTI、EXEC、DISCARD等命令实现。此外,Redis提供WATCH和UNWATCH机制,用于监控键变化,实现类似“乐观锁”的功能,提升并发操作的安全性。
|
4月前
|
存储 缓存 监控
Redis设计与实现——Redis命令参考与高级特性
Redis 是一个高性能的键值存储系统,支持丰富的数据类型(字符串、列表、哈希、集合等)和多种高级功能。本文档涵盖 Redis 的核心命令分类,包括数据类型操作、事务与脚本、持久化、集群管理、系统监控等。特别介绍了事务的原子性特性、Lua 脚本的执行方式及优势、排序机制、发布订阅模型以及慢查询日志和监视器工具的使用方法。适用于开发者快速掌握 Redis 常用命令及其应用场景,优化系统性能与可靠性。
|
17天前
|
存储 缓存 NoSQL
Redis基础命令与数据结构概览
Redis是一个功能强大的键值存储系统,提供了丰富的数据结构以及相应的操作命令来满足现代应用程序对于高速读写和灵活数据处理的需求。通过掌握这些基础命令,开发者能够高效地对Redis进行操作,实现数据存储和管理的高性能方案。
57 12
|
16天前
|
存储 消息中间件 NoSQL
【Redis】常用数据结构之List篇:从常用命令到典型使用场景
本文将系统探讨 Redis List 的核心特性、完整命令体系、底层存储实现以及典型实践场景,为读者构建从理论到应用的完整认知框架,助力开发者在实际业务中高效运用这一数据结构解决问题。
|
27天前
|
存储 缓存 人工智能
Redis六大常见命令详解:从set/get到过期策略的全方位解析
本文将通过结构化学习路径,帮助读者实现从命令语法掌握到工程化实践落地的能力跃迁,系统性提升 Redis 技术栈的应用水平。
|
2月前
|
NoSQL Redis
Lua脚本协助Redis分布式锁实现命令的原子性
利用Lua脚本确保Redis操作的原子性是分布式锁安全性的关键所在,可以大幅减少由于网络分区、客户端故障等导致的锁无法正确释放的情况,从而在分布式系统中保证数据操作的安全性和一致性。在将这些概念应用于生产环境前,建议深入理解Redis事务与Lua脚本的工作原理以及分布式锁的可能问题和解决方案。
126 8
|
4月前
|
存储 缓存 NoSQL
Redis中的常用命令-get&set&keys&exists&expire&ttl&type的详细解析
总的来说,这些Redis命令提供了处理存储在内存中的键值对的便捷方式。通过理解和运用它们,你可以更有效地在Redis中操作数据,使其更好地服务于你的应用。
350 17
|
4月前
|
缓存 NoSQL 关系型数据库
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
|
9天前
|
存储 缓存 NoSQL
Redis专题-实战篇二-商户查询缓存
本文介绍了缓存的基本概念、应用场景及实现方式,涵盖Redis缓存设计、缓存更新策略、缓存穿透问题及其解决方案。重点讲解了缓存空对象与布隆过滤器的使用,并通过代码示例演示了商铺查询的缓存优化实践。
70 1
Redis专题-实战篇二-商户查询缓存