Redis之事务

这篇具有很好参考价值的文章主要介绍了Redis之事务。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

Redis事务命令(开启事务、提交事务、取消事务、监视)、乐观锁、悲观锁。


一、概述

Redis事务的本质是一组命令的集合

事务支持一次执行多个命令,一个事务中所有命令都会被序列化。
在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会插入到事务执行命令序列中。
所以说:Redis 事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令。

事务支持一次执行多个命令,一个事务中所有命令都会被序列化。

批量操作在发送 EXEC 命令前被放入队列缓存,并不会被实际执行。

Redis 事务不保证原子性

Redis中,单条命令是原子性执行的,但事务不保证原子性,且没有回滚。
事务中任意命令执行失败,其余的命令仍会被执行。

Redis事务的三个阶段

  • 开启事务
  • 命令入队
  • 执行事务

二、实例演示

1.正常执行事务

127.0.0.1:6379> multi  # 开启事务
OK
## 命令入队
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> set k4 v4
QUEUED
127.0.0.1:6379(TX)> exec # 执行事务
OK
OK
OK

2.取消事务

127.0.0.1:6379> multi # 开启事务
OK
# 命令入队
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> discard # 取消事务,事务队列中命令都不会执行
OK
127.0.0.1:6379> DBSIZE # 可以看出set命令未执行
0

3.编译型异常

若在事务队列中存在命令性错误(类似于java编译性错误),则执行 exec 命令时,所有命令都不会执行。

127.0.0.1:6379> flushall
OK
127.0.0.1:6379> multi
OK
# 命令入队
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> getset k2 # 错误命令
ERR wrong number of arguments for 'getset' command

127.0.0.1:6379(TX)> set k3 v3  # 命令入队
QUEUED
127.0.0.1:6379(TX)> exec # 执行事务,报错 ,所有命令都不执行
EXECABORT Transaction discarded because of previous errors.

4.运行时异常

若在事务队列中存在语法性错误(类似于 Java 的的运行时异常),则执行exec命令时,其他正确命令会被执行,错误命令抛出异常。

127.0.0.1:6379> set k1 v1 # k1的值为字符串,无法实现增减
OK
127.0.0.1:6379> multi # 开启事务
OK
127.0.0.1:6379(TX)> incr k1 # 执行失败
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> get k2
QUEUED
127.0.0.1:6379(TX)> exec 
ERR value is not an integer or out of range # 第一条命令报错,其他命令正常执行
OK
v2

5.监听

watch(乐观锁实现)

  • 悲观锁
    悲观锁(Pessimistic Lock),顾名思义,就是很悲观。
    每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁。
    这样别人想拿到这个数据就会 block 直到它拿到锁。
    传统的关系型数据库里面就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在操作之前先上锁。
  • 乐观锁
    乐观锁(Optimistic Lock),顾名思义,就是很乐观。
    每次去拿数据的时候都认为别人不会修改,所以不会上锁。
    但是在更新的时候会判断一下再此期间别人有没有去更新这个数据,可以使用版本号等机制。
    乐观锁适用于多读的应用类型,这样可以提高吞吐量。
    乐观锁策略:提交版本必须大于记录当前版本才能执行更新。

(1)事务过程未有数据改变

127.0.0.1:6379> set money 100 # 余额
OK
127.0.0.1:6379> set out 0 # 支出
OK
127.0.0.1:6379> watch money # 监视money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> DECRBY money 20 # 余额减20
QUEUED
127.0.0.1:6379(TX)> INCRBY out 20 # 支出金额多20
QUEUED
127.0.0.1:6379(TX)> exec # 提交事务,成功执行
1) (integer) 80
2) (integer) 20

(2)事务过程其他线程改变数据

利用多线程测试
窗口1:

127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> DECRBY money 10
QUEUED
127.0.0.1:6379(TX)> INCRBY out 10
QUEUED

窗口2:

127.0.0.1:6379> get money
"80"
127.0.0.1:6379> set money 200
OK

窗口1:

127.0.0.1:6379(TX)> exec # 事务提交,执行失败
(nil)

在窗口1事务提交前,窗口2修改了money的值。所以窗口1提交事务,执行失败。

解决:
窗口1:文章来源地址https://www.toymoban.com/news/detail-745695.html

127.0.0.1:6379> unwatch # 执行失败就先解除监听
OK
127.0.0.1:6379> watch money # 获取新值,重新监听,开启事务
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> DECRBY money 10
QUEUED
127.0.0.1:6379(TX)> INCRBY out 10
QUEUED
127.0.0.1:6379(TX)> exec # 提交事务,执行成功(对比监视的值是否发生变化,没有则执行成功,否则失败)
1) (integer) 190
2) (integer) 30


总结

  • 一旦执行exec开启事务后,无论事务是否执行成功, watch 对变量的监听都将被取消。
  • 当事务执行失败后,需重新执行 watch 命令对变量进行监听,并开启新的事务进行操作。
  • watch 指令类似于乐观锁,在事务提交时,如果 watch 监控的多个 key 中任何 key 的值已经被其他客户端更改。则使用 exec 执行事务时,事务队列将不会被执行,同时返回 (nil) 应答以通知调用者事务执行失败。

到了这里,关于Redis之事务的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Redis---数据库和缓存如何保证一致性?

    用「读 + 写」请求的并发的场景来分析: 假如某个用户数据在缓存中不存在,请求 A 读取数据时从数据库中查询到年龄为 20,在未写入缓存中时另一个请求 B 更新数据。它更新数据库中的年龄为 21,并且清空缓存。这时请求 A 把从数据库中读到的年龄为 20 的数据写入到缓存

    2024年01月24日
    浏览(41)
  • Redis如何保证缓存和数据库一致性?

    现在我们在面向增删改查开发时,数据库数据量大时或者对响应要求较快,我们就需要用到Redis来拿取数据。 Redis:是一种高性能的内存数据库,它将数据以键值对的形式存储在内存中,具有读写速度快、支持多种数据类型、原子性操作、丰富的特性等优势。 优势: 性能极高

    2024年01月16日
    浏览(54)
  • 自学WEB后端05-Node.js后端服务链接数据库redis

    嘿,亲爱的小伙伴们!😄 今天我要给大家分享一个超级方便且高效的 NoSQL 类型数据库——Redis!💡 它可不是一般的关系型数据库哦,而是以键值对形式存储数据的内存数据库。📚 快跟着我一起来学习如何安装和使用 Redis 吧!  自学WEB后端01-安装Express+Node.js框架完成Hello

    2024年02月07日
    浏览(36)
  • Redis如何保障缓存与数据库的数据一致性问题?

    目录 一.最经典的数据库加缓存的双写双删模式 二. 高并发场景下的缓存+数据库双写不一致问题分析与解决方案设计 三、上面高并发的场景下,该解决方案要注意的问题 1.1 Cache Aside Pattern概念以及读写逻辑 (1)读的时候,先读缓存,缓存没有的话,那么就读数据库,然后取

    2023年04月21日
    浏览(36)
  • 数据库缓存服务——NoSQL之Redis配置与优化

    目录 一、缓存概念 1.1 系统缓存 1.2 缓存保存位置及分层结构 1.2.1 DNS缓存 1.2.2 应用层缓存 1.2.3 数据层缓存 1.2.4 硬件缓存 二、关系型数据库与非关系型数据库 2.1 关系型数据库 2.2 非关系型数据库 2.3 关系型数据库和非关系型数据库区别: 2.4 非关系型数据库产生背景 2.5 总结

    2024年02月15日
    浏览(36)
  • Redis数据库 | 发布订阅、主从复制、哨兵模式、缓存雪崩

    💗wei_shuo的个人主页 💫wei_shuo的学习社区 🌐Hello World ! Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息 Redis 客户端可以订阅任意数量的频道 Redis主从复制是指在Redis中设置一个主节点(Master)和一个或多个从节点(Slave),

    2024年02月15日
    浏览(35)
  • Springboot+Redis:实现缓存 减少对数据库的压力

    🎉🎉欢迎光临,终于等到你啦🎉🎉 🏅我是苏泽,一位对技术充满热情的探索者和分享者。🚀🚀 🌟持续更新的专栏 Redis实战与进阶 本专栏讲解Redis从原理到实践 这是苏泽的个人主页可以看到我其他的内容哦👇👇 努力的苏泽 http://suzee.blog.csdn.net/   目录 缓存如何实现?

    2024年03月24日
    浏览(41)
  • redis面试题目-如何保证数据库与缓存的数据一致性

    原视频:https://www.bilibili.com/video/BV1Km4y1r75f?p=62vd_source=fa75329ae3880aa55609265a0e9f5d34 由于缓存和数据库是分开的,无法做到原子性的同时进行数据修改,可能出现缓存更新失败,或者数据库更新失败的情况,这时候会出现数据不一致,影响前端业务 先更新数据库,再更新缓存。缓

    2024年02月05日
    浏览(47)
  • Redis缓存MySQL数据库存储二者如何保证数据一致性

    在大型互联网应用中,由于数据库读写频繁、压力大等原因,我们通常会使用缓存来减少数据库的访问次数,提高系统的性能。而Redis作为一个高性能的内存数据库,成为了缓存的首选方案之一。但是,缓存和数据库之间存在数据一致性的问题,如何解决这个问题呢?本文将

    2023年04月19日
    浏览(39)
  • 如何保证Redis缓存和数据库的一致性问题

    熟练掌握Redis缓存技术? 那么请问Redis缓存中有几种读写策略,又是如何保证与数据库的一致性问题 今天来聊一聊常用的三种缓存读写策略 首先我们来思考一个问题 写 先更新缓存 再更新数据库 首先如果缓存更新成功但数据库更新失败,会导致数据不一致的问题 其次当请求

    2024年02月14日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包