Java开发 - Redis事务怎么用?

news2024/10/7 8:30:50

前言

最近博主感觉捅了Redis窝,从Redis主从,哨兵,集群,集群原理纷纷讲了一遍,不知道大家都学会了多少,想着送佛送到西,不如再添一把火,所以今天带给大家的博客是Redis事务!有人要问,什么?Redis也有事务?没错,Redis也有类似于MySQL的事务,不要惊奇,这也不是刚刚有,只是很多人平时不常用罢了。

事务

事务我们知道,是存在于关系型数据库中的一种数据处理手段,主要责任是数据的CRUD,还包括了事务提交和回滚。那么在Redis里,有没有一种机制也能处理数据的提交和回滚呢?答案是肯定的,那就是Redis事务,它是一个类原子的隔离操作,将一系列指令按需排队并顺序执行,期间不会被其他指令插队。但,Redis事务在运行时无法预测,所以也无法回滚。

指令

在Redis事务中,共有三大指令:

  • multi:开启事务
  • exec:执行事务
  • discard:取消事务

在multi之后开启事务,此时可以set多个key,这些key将按照顺序存入先进先出的队列,exec执行事务,这些事务将按照入队的顺序执行,在这些事务执行过程中,不受其他的插入指令影响。在组队阶段使用discard指令,由于未使用exec指令开启事务,所以前面队列中的操作将全部取消。

我们来做个演示,首先开启一个Redis服务:

redis-server redis1.conf

连接redis:

redis-cli -h localhost -p 6379

正常执行

取消执行

因为没有执行exec,所以discard后,前面的c和d都不会执行。

组队错误 

可以看到,在组队时抱了错,事务是不会执行的。

执行错误 

我们在set c之后对c进行+1操作,由于c不是integer类型,所以报错了,但是我们发现,最终c和d被存储进了redis,从这一点来看,运行过程中的异常不会导致队列中的任务取消。

Redis和锁 

为了保证数据的安全性,我们有时候在做key的存储的时候会给key加锁,防止多个线程的情况下key被篡改去情况发生,一般发生在抢购/秒杀时对库存的操作上。

被关锁就不再多提了,使用被关锁可以完全防止key被篡改,但相应的,线程也将被阻塞,降低效率,这里说说乐观锁在redis里的使用,我们看如下操作。

首先我们需要再开一个命令行,模拟两个线程的场景:

在开始前,我们先通过flushdb指令清空redis中的数据:

监听key并开启事务

线程1:

线程2:

操作并提交key

线程1:

线程2:

可以看到线程2在对a+1的时候出问题了,返回nil。像不像CAS,没错,乐观锁的本质就是CAS,比较并交换,比较的值被改变了,自然不会存入新值。

回滚与原子性

Redis回滚

那有人要问了 ,redis到底能不能回滚?其实在上面我们已经得到了答案,就是在组队阶段是可以回滚的,看“组队错误”,在执行阶段是不支持回滚的,看“执行错误”。

所以,最终我们得出结论,在使用中,redis可支持回滚,但是情况比较复杂,是一种可预知的错误,而那些不可预知的错误,则是无法回滚。

原子性

基于以上redis事务执行时出现的组队和执行问题,所以利用redis做库存的扣减似乎是一件不太稳妥的事,所以,为了弥补这个缺陷,我们需要使用redis的原子性。原子性的特点就是:要么一起执行,要么不执行。这里我们应该都听说一个东西叫lua脚本,其特点我就不多说了,总之就是执行快且保证原子性(不被打断),但是,lua脚本也不支持回滚,所以关于redis的回滚,大家就不要纠结了。

Spring Boot接入Redis事务

关于Spring Boot接入Redis事务,怎么说呢?感觉没太大必要,哈哈,不过也不能说一无是处,用还是有人在用的,这里博主就简单讲讲怎么用。

启动Redis服务

上面Redis已经启动了,直接用。 

redisTemplate使用事务

添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

添加配置

spring.redis.host=127.0.0.1
spring.redis.port=6379

 准备测试代码

    @Test
    void testTransaction() {
        //开启事务支持
        redisTemplate.setEnableTransactionSupport(true);
        //开启事务
        redisTemplate.multi();
        redisTemplate.opsForValue().set("name1", "codingfire1");
        redisTemplate.opsForValue().set("name2", "codingfire2");

        //执行事务
        redisTemplate.exec();
        System.out.println(redisTemplate.opsForValue().get("name1"));
        System.out.println(redisTemplate.opsForValue().get("name2"));
    }

以上代码在运行的时候发现报错了:

但是当我打开redis可视化工具查看时发现数据已经存进去了:

官方是通过Jedis来实现事务的,所以这个问题出现了还让人有点懵,很多人说是因为没开启事务支持,但是博主明显开启了,所以有些无从解答了,有知道原因的可以告诉博主。

但是活人不能让尿憋死啊,有一种SessionCallback的方式是很多人都推荐使用的,我们来看看:

    @Test
    public void testTransaction2(){
        redisTemplate.execute(new SessionCallback<List<Object>>(){
            @Override
            public List<Object> execute(RedisOperations operations) throws DataAccessException {
                operations.multi();
                operations.opsForValue().set("name3","codingfire3");
                operations.opsForValue().set("name4","codingfire4");
                operations.opsForValue().set("name5","codingfire5");
                return redisTemplate.exec();
            }
        });
    }

 执行后没报错,我们看下redis可视化工具:

测试成功。

Jedis引入

我们刚刚提到了一种Jedis实现的方式,下面我们来说说Jedis怎么实现。 

添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.3.0</version>
</dependency>

添加配置

spring.redis.host=127.0.0.1
spring.redis.port=6379

 准备测试代码

    @Test
    public void testTransaction3(){
        Jedis jedis =new Jedis("127.0.0.1",6379);
        ;//开启事务
        Transaction transaction = jedis.multi();
        try {
            transaction.set("key1", "v1");
            //制造异常,测试取消事务
            //int i=1/0;
            transaction.set("key2", "v2");
            //执行事务
            transaction.exec();
        }catch (Exception e){
            //取消事务
            transaction.discard();
            e.printStackTrace();
        }
    }

查看redis可视化工具:

测试成功。 

结语

以上是对redis事务的一个实操过程,建议大家在做key的存入的时候不要对多个key进行关联,主要是避免出现数据不一致的情况。整体上就是这样,推荐使用SessionCallback和Jedis的方式,虽然你可能不一定会用到这东西,但是万一用到了呢?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/846495.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2.4g遥控台灯开发方案,采用宇凡微2.4g合封芯片

普通台灯光源光谱固定且有频闪&#xff0c;长时间使用容易导致眼部疲劳。宇凡微推出的护眼台灯方案&#xff0c;具有无极色温调节&#xff0c;光线柔和不刺眼、无频闪&#xff0c;具有多种功能模式&#xff0c;可用2.4g遥控器调节。 一、遥控护眼台灯方案介绍 护眼台灯方案采用…

Progress in Neurobiology:大脑活动的自主模式

摘要 自主神经系统和中枢神经系统之间的相互作用对人脑功能和健康的相关性尚不清楚&#xff0c;尤其是当这两个系统都受到睡眠剥夺(SD)的挑战时。本研究测定了健康参与者的大脑活动(采用fMRI)、脉冲和呼吸信号&#xff0c;以及β-淀粉样蛋白负荷(采用PET)。研究结果发现&#…

Jtti:Ubuntu静态IP地址怎么配置

在 Ubuntu 中配置静态 IP 地址需要编辑网络配置文件。以下是在 Ubuntu 20.04 版本中配置静态 IP 地址的步骤&#xff1a; 打开终端&#xff0c;以管理员身份登录或使用 sudo 权限。 使用以下命令打开网络配置文件进行编辑&#xff1a; sudo nano /etc/netplan/00-installer-…

使用PhpSpreadsheet 导出excel文件根据数据判断设置文字颜色

public function index(){//接收前端参数 查询数据出来 目前演示为测试数据$data [["id" > 1,"name" > "小黄","age" > "10"],["id" > 2,name > "小红","age" > "11…

Python(Web时代)——jinja2模板

简介 Jinja2是Flask框架默认支持的模板引擎&#xff0c;是python的web项目中被广泛应用的一种模板引擎&#xff0c;jinja2的作者与Flask是同一个人。 jinja2具有以下特点&#xff1a; 非常灵活&#xff0c;提供了控制结构、表达式与继承等 性能好 可读性强 渲染一个模板&a…

python_day19_递归

拓展 import osdef test_os():# 列出路径下内容print(os.listdir("D:/阿里云"))# 指定路径是否为文件夹print(os.path.isdir("D:/阿里云"))# 指定路径是否存在print(os.path.exists("D:/阿里云"))if __name__ __main__:test_os()递归查文件 每…

Web安全——Burp Suite基础上

Burp Suite基础 一、Burp Suite安装和环境配置如何命令行启动Burp Suite 二、Burp Suite代理和浏览器设置FireFox设置 三、如何使用Burp Suite代理1、Burp Proxy基本使用2、数据拦截与控制3、可选项配置Options客户端请求消息拦截服务器端返回消息拦截服务器返回消息修改正则表…

杰理-改变文字背景颜色

杰理-改变文字背景颜色 text->elm.css.background_color RGB565(100,0,0);

SIMATIC WINCC V8.0安装教程(Win11系统)

SIMATIC WINCC V8.0安装教程(Win11系统) 1. 首先,安装之前需要检查软件与操作系统的兼容性,否则在安装或者使用过程中会出现各种问题。 以WinCC V8.0为例,兼容性列表列出与之兼容的操作系统版本以及注意事项,图中打钩的部分为兼容,没有打钩的部分为不兼容。 2. 在window…

贝叶斯学习

贝叶斯 贝叶斯学习的背景贝叶斯定理举例 概览选择假设— MAPMAP举例 选择假设 — 极大似然 MLML 举例: 抛硬币问题 极大似然 & 最小二乘Nave Bayesian Classifier (朴素贝叶斯分类器)举例1&#xff1a;词义消歧 (Word Sense Disambiguation)举例 2: 垃圾邮件过滤 从垃圾邮件…

2023最新 Dreamweaver 下载安装教程(非常详细)从零基础入门到精通,看完这一篇就够了(附安装包)

软件介绍 Dreamweaver简称“DW”&#xff0c;是一款专业的网页设计软件&#xff0c;集网页制作和网站管理于一身的即时检索的网页代码编辑器&#xff0c;利用对 HTML、CSS、JavaScript 等内容的支持&#xff0c;设计人员和开发人员可以在几乎任何地方快速制作并发布网页。借助…

https证书的作用是什么?

如今很多企业都有属于自己的网站&#xff0c;因为当今是网络时代&#xff0c;企业借助网站基本的发展会更加好。 网站的安全性是很重要的&#xff0c;一旦安全无法保障&#xff0c;就容易出现敏感信息被盗用的情况&#xff0c;这对企业是非常不利的&#xff0c;这个时候就需要…

图像提示词攻略--基于 stable diffusion v2

Stable Diffusion 是一种潜在的文本到图像扩散模型&#xff0c;能够在给定任何文本输入&#xff08;称为提示&#xff09;的情况下生成逼真的图像。 在本文中&#xff0c;我将讨论和探索一些提高提示有效性的方法。从在提示中添加某些关键字和组合词、从更改单词顺序及其标点符…

Vue中监听路由参数变化的几种方式

目录 一. 路由监听方式&#xff1a; 通过 watch 进行监听 1. 监听路由从哪儿来到哪儿去 2. 监听路由变化获取新老路由信息 3. 监听路由变化触发方法 4. 监听路由的 path 变化 5. 监听路由的 path 变化, 使用handler函数 6. 监听路由的 path 变化&#xff0c;触发method…

iOS 实现图片高斯模糊效果

效果图 用到了 UIVisualEffectView 实现代码 - (UIVisualEffectView *)bgEffectView{if(!_bgEffectView){UIBlurEffect *blur [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];_bgEffectView [[UIVisualEffectView alloc] initWithEffect:blur];}return _bgEffect…

QCustomPlot 给出的测试用例图示

0 1 2 3 4 5 6 7 8 9 10 移动 11 12 13 14 15 移动 16 17 18 19 20

高翔《自动驾驶中的SLAM技术》代码详解 — 第6章 2D SLAM

目录 6.2 扫描匹配算法 6.2.1 点到点的扫描匹配 6.2 扫描匹配算法 6.2.1 点到点的扫描匹配 // src/ch6/test_2dlidar_io.cc // Created by xiang on 2022/3/15. // #include <gflags/gflags.h> #include <glog/logging.h> #include <opencv2/highgui.hpp>…

Vue3如何获取和操作DOM元素

Vue3如何获取和操作DOM元素 环境&#xff1a;vue3tsvite 目标&#xff1a; 1.修改DOM的文本值和样式 2.获取后代子DOM元素,操作修改 <template><div class"content"><h1>演示</h1><p ref"pText1">这是ref为pText1的一段文…

【网络编程】揭开套接字的神秘面纱

文章目录 1 :peach:简单理解TCP/UDP协议 :peach:2 :peach:网络字节序 :peach:3 :peach:socket编程接口 :peach:3.1 :apple:socket 常见API :apple:3.2 :apple:sockaddr结构:apple: 4 :peach:简单的UDP网络程序 :peach:4.1 :apple:基本分析:apple:4.2 :apple:udpServer.hpp(重点…

海外跨境电商网站多语言一键翻译系统开发(java开源)

要搭建一个海外跨境电商网站多语言一键翻译系统&#xff0c;可以按照以下步骤进行&#xff1a; 1. 确定需求&#xff1a;首先&#xff0c;需要明确系统的功能需求和用户需求。例如&#xff0c;确定需要支持哪些语种&#xff0c;界面翻译和数据库翻译的具体要求等。 2. 选择开…