【征服redis2】redis的事务介绍

目录

目录

1.redis事务介绍

2 事务出错的处理

3.Java如何使用redis事务


1.redis事务介绍

在前面我们介绍了redis的几种典型数据结构和应用,本文我们来看一下redis的事务问题。事务也是数据库的重要主题,熟悉关系型数据库的读者应该对事务比较了解,简单地说,事务表示一组动作,要么全部执行,要么全部不执行。例如在社交网站上用户 A关注了用户B,那么需要在用户A的关注表中加入用户B,并且在用户B的粉丝表中添加用户A,这两个行为要么全部执行,要么全部不执行,否则会出现数据不一致的情况。

Redis提供了简单的事务功能,将一组需要一起执行的命令放到 multi和exec两个命令之间。multi命令代表事务开始,exec命令代表事务 结束,它们之间的命令是原子顺序执行的,例如下面操作实现了上述用户关注问题。

127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> sadd user:a:follow user:b
QUEUED
127.0.0.1:6379(TX)> sadd user:b:fans user:a
QUEUED

可以看到sadd命令此时的返回结果是QUEUED,代表命令并没有真 正执行,而是暂时保存在Redis中。如果此时另一个客户端执行 sismember user:a:follow user:b返回结果应该为0。

127.0.0.1:6379> sismember user:a:follow user:b
(integer) 0

只有当exec执行后,用户A关注用户B的行为才算完成,如下所示返回的两个结果对应sadd命令。

第一个终端:
127.0.0.1:6379(TX)> exec
1) (integer) 1
2) (integer) 1第二个终端:
127.0.0.1:6379> sismember user:a:follow user:b
(integer) 1

如果要停止事务的执行,可以使用discard命令代替exec命令即可。

2 事务出错的处理

如果事务中的命令出现错误,Redis的处理机制也不一样。

情况1.命令错误

例如下面操作错将set写成了sett,属于语法错误,会造成整个事务无法执行,key和counter的值未发生变化。

比如说我们按照下面的方式来执行redis事务:

127.0.0.1:6379> mget key counter

1) "2"

2) "100"

127.0.0.1:6379> 

127.0.0.1:6379> multi

OK

127.0.0.1:6379(TX)> sett key world

(error) ERR unknown command `sett`, with args beginning with: `key`, `world`, 

127.0.0.1:6379(TX)> incr counter

QUEUED

127.0.0.1:6379(TX)> exec

(error) EXECABORT Transaction discarded because of previous errors.

127.0.0.1:6379> mget key counter

1) "2"

2) "100"

127.0.0.1:6379> 

可以看到最后的counter并没有发生变化。

情况2.运行时错误

例如用户B在添加粉丝列表时,误把sadd命令写成了zadd命令,这种就是运行时命令,因为语法是正确的,redis是无法察觉到这种错误的。例如:

127.0.0.1:6379> multi

OK

127.0.0.1:6379(TX)> sadd user:a:follow user:b

QUEUED

127.0.0.1:6379(TX)> zadd user:b:fans 1 user:a

QUEUED

127.0.0.1:6379(TX)> exec

1) (integer) 0

2) (error) WRONGTYPE Operation against a key holding the wrong kind of value

127.0.0.1:6379> sismember user:a:follow user:b

(integer) 1

127.0.0.1:6379> 

可以看到Redis并不支持回滚功能,sadd user:a:follow user:b命令已经执行成功,开发人员需要自己修复这类问题。

有些应用场景需要在事务之前,确保事务中的key没有被其他客户 端修改过,才执行事务,否则不执行(类似乐观锁)。Redis提供了watch命令来解决这类问题,下表展示了添加watch之后两个客户端执行命令的时序。

可以看到“客户端-1”在执行multi之前执行了watch命令,“客户 端-2”在“客户端-1”执行exec之前修改了key值,造成事务没有执行(exec 结果为nil),整个代码如下所示:

客户端1:

127.0.0.1:6379> set key "java"

OK

127.0.0.1:6379> watch key

OK

127.0.0.1:6379> multi

OK

此时客户端2执行:

append key python

然后回到客户端1:

127.0.0.1:6379(TX)> append key jedis

QUEUED

127.0.0.1:6379(TX)> exec

(nil)

127.0.0.1:6379> get key

"javapython"

127.0.0.1:6379>

Redis提供了简单的事务,之所以说它简单,主要是因为它不支持 事务中的回滚特性,同时无法实现命令之间的逻辑关系计算,当然也体现了Redis的“keep it simple”的特性,下一小节介绍的Lua脚本同样可以实现事务的相关功能,但是功能要强大很多。

3.Java如何使用redis事务

我们前面通过redis客户端命令来学习了事务,在程序中,我们一定是让java调用某个api来实现这些功能的。

我们介绍过jedis的用法,使用jedis来实现事务功能的代码也非常简单:

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;public class JedisTransactionDemo {public static void main(String[] args) {Jedis jedis = new Jedis("localhost", 6379);Transaction transaction = jedis.multi(); // 开启事务try {transaction.set("name", "哈哈");transaction.set("age", "18");transaction.exec(); // 提交事务} catch (Exception e) {transaction.discard(); // 回滚事务} finally {jedis.close(); // 关闭连接}}
}

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

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

相关文章

erlang (OS 操作模块)学习笔记

cmd: env: 返回所有环境变量的列表。 每个环境变量都表示为元组 {VarName,Value},其中 VarName 是 变量和 Value 其值。 例: {VarName,Value} {"ERLANG_HOME","C:\\Program Files\\erl-24.3.4.2\\bin\\erl-24.3.4.2"}…

2023我的总结:读书、写作、运动、爱家人、学一门手艺

不知不觉中,2024年1月已过去大半了,按照惯例,还是对过去一年的所思所行做个简单的汇报。也希望我的一些经历,能给到正在做年终总结或新年规划的朋友,一些参考。 01 读书,是门槛最低的高贵 最近一段时间&am…

gh0st远程控制——客户端界面编写(二)

● 补充小知识:枚举类型的使用 每个控件(比如列表)都对应一个自己的唯一的变量 使用枚举类型可以将变量名与编号进行绑定,以后程序需要扩展的时候,只需要在定义枚举变量的位置重新修改编号就可以了,这样全…

Linux shell编程学习笔记40:stat命令

程序员必备的面试技巧 “程序员必备的面试技巧,就像是编写一段完美的代码一样重要。在面试战场上,我们需要像忍者一样灵活,像侦探一样聪明,还要像无敌铁金刚一样坚定。只有掌握了这些技巧,我们才能在面试的舞台上闪耀…

htb monitored root方式其中的一种(仅作记录)

快下班时候审出来的,目前root的第5种方式 nagiosmonitored:~$ cat /usr/local/nagiosxi/scripts/backup_xi.sh #!/bin/bash # # Creates a Full Backup of Nagios XI # Copyright (c) 2011-2020 Nagios Enterprises, LLC. All rights reserved. #BASEDIR$(dirname …

SCI 2区论文:医疗保健中心训练有素的脑膜瘤分割模型的性能测试-基于四个回顾性多中心数据集的二次分析

基本信息 标题:Performance Test of a Well-Trained Model for Meningioma Segmentation in Health Care Centers: Secondary Analysis Based on Four Retrospective Multicenter Data Sets中文标题:医疗保健中心训练有素的脑膜瘤分割模型的性能测试&am…

PE解释器之PE文件结构(二)

接下来的内容是对IMAGE_OPTIONAL_HEADER32中的最后一个成员DataDirectory,虽然他只是一个结构体数组,每个结构体的大小也不过是个字节,但是它却是PE文件中最重要的成员。PE装载器通过查看它才能准确的找到某个函数或某个资源。 一&#xff1…

软件测试|sqlalchemy一对一关系详解

简介 SQLAlchemy 是一个强大的 Python ORM(对象关系映射)库,它允许我们将数据库表映射到 Python 对象,并提供了丰富的关系模型来处理不同类型的关系,包括一对一关系。在本文中,我们将深入探讨 SQLAlchemy …

Ubuntu使用QtCreator + CMake 开发C/C++程序

平台 OS: Ubuntu 20.04 cmake: 3.16.3 IDE: Qt Creator 4.11.1 Based on Qt 5.14.1 (GCC 5.3.1 20160406 (Red Hat 5.3.1-6), 64 bit) Built on Feb 5 2020 12:48:30 From revision b2ddeacfb5 Copyright 2008-2019 The Qt Company Ltd. All rights reserved. The program …

Hugging Face怎么通过国内镜像去进行模型下载(hf-mirror.com)

一、引言 Hugging Face 🤗是一家专注于自然语言处理(NLP)技术的公司,以其开源贡献和先进的机器学习模型而闻名。该公司最著名的产品是 Transformers 库,这是一个广泛使用的 Python 库,它提供了大量预训练模…

(Bean实例化的基本流程 )学习Spring的第六天

Bean实例化的基本流程 其实可以解释为三个过程: 1 . 有关Bean的信息被封装成一个map集合 : DeanDefinitionMap . key为Bean的名称 , value为有关<bena>标签的信息 2 . Spring框架对这个存储Bean信息的Map进行遍历 , 进行创建对象 , 把创建好的对象存储到另一个Map集合里…

深入理解 Kubernetes Ingress:路由流量、负载均衡和安全性配置

Kubernetes Ingress 是 Kubernetes 集群中外部流量管理的重要组件。它为用户提供了一种直观而强大的方式&#xff0c;通过定义规则和配置&#xff0c;来控制外部流量的路由和访问。 1. 什么是 Ingress&#xff1f; 在 Kubernetes 中&#xff0c;Ingress 是一种 API 资源&#…

取代房子,中国又一种资本在崛起(深度)

我一直有一个观点&#xff1a;经济形势好的时候&#xff0c;只要不是夕阳行业&#xff0c;做什么都能过得不错。经济形势差的时候&#xff0c;对于个人来说&#xff0c;拼的就是学习能力。 10年前&#xff0c;在市场上很吃香的是MBA&#xff0c;那时候企业需要高速发展&#x…

JVM工作原理与实战(二十):直接内存

专栏导航 JVM工作原理与实战 RabbitMQ入门指南 从零开始了解大数据 目录 专栏导航 前言 一、直接内存 1.直接内存作用 二、在直接内存上创建数据 总结 前言 JVM作为Java程序的运行环境&#xff0c;其负责解释和执行字节码&#xff0c;管理内存&#xff0c;确保安全&…

Spring Cloud详细入门使用

文章目录 Spring Cloud服务注册与发现EurekaServer 启动服务注册服务发现 NacosServer启动 (nacos2.2.0)服务注册服务发现服务集群命名空间配置中心集群搭建 负载均衡RPC远程过程调用Feign使用 网关路由断言工厂网关过滤工厂跨域处理全局跨域配置单个微服务跨域配置 限流 熔断 …

Codeforces Round 919 (Div. 2) A~E

A. Satisfying Constraints(模拟) 题意&#xff1a; 给出 n n n个限制条件&#xff0c;问有多少个数字 k k k同时满足这些限制条件。 限制条件分为以下三种&#xff1a; k k k必须大于等于给出的一些数字 x x x k k k必须小于等于给出的一些数字 x x x k k k不能与给出的…

定时器开发基础

1定时器的基本概述 通过滴漏和漏沙瓶这两个例子简单讲述定时器的基本工作原理。 STM32的常见的定时器资源&#xff1a; 系统嘀嗒定时器SysTick、看门狗定时器WatchDog、实时时钟RTC、基本定时器、通用定时器、高级定时器。 系统嘀嗒定时器SysTick &#xff1a;这是一个集成在C…

JavaScript 自定义分页组件

仿boostrap 前端分页组件的实现 一 写一个前端自定义分页组件&#xff0c;需要考虑以下问题 需要一个<ul id"pagination"></ul>标签 total; // 总数据的数量 pageSize; // 一页显示数量 pageIndex; // 当前页 二 实现细节 编写html文件 index.html…

蓝桥杯(C++ 整数删除 优先队列 )

优先队列&#xff1a; 优先队列具有队列的所有特性&#xff0c;包括队列的基本操作&#xff0c;只是在这基础上添加了内部的一个排序&#xff0c;它本质是一个堆实现的。 1.头文件&定义 #include <queue> #include <functional> //greater<>// 定义 p…