SpringCloudAliBaba篇之Seata:分布式事务组件理论与实践
1、事务简介
事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。在关系数据库中,一个事务由一组SQL语句组成,事务具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID原则。
- 原子性(atomicity): 事务中的操作要么都发生,要么都不发生
- 一致性(consistency): 事务从一个一致性的状态变到另一个一致性的状态,
- 隔离性(isolation): 事务之间不能相互干扰、相互隔离,隔离又分为四个级别: 读未提交(read uncommitted), 读已提交(read committed,解决脏读)、可重复读(rpeatable read ,解决不可重复读)、串行化(serializable 解决幻读)
- 持久性(durability): 持久性也称为永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变是永久的,接下来的操作或故障不应该对其有任何影响。
1.1、本地事务
@Translation
大多数场景下,我们的应用都只需要操作单一的数据库,这种情况的事务我们称之为本地事务(Local Transation
)。本地事务的ACID特性是数据库直接提供支持。本地事务应用架构如下所示:
1.2、常见的分布式事务解决方案
- seata阿里分布式事务框架
- 消息队列
- saga
- XA
他们都有一个共同点,都是两阶段(2PC)。两阶段是指完成整个分布式事务,划分成两个步骤完成。
这四种常见的分布式事务解决方法,分别对应着分布式事务的四种模式:AT、TCC、Sage、XA
;
2、Seata是什么
seata是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata将为用户提供了AT、TCC、SAGA和XA事务模式,为用户打造一站式的分布式解决方案。AT模式是阿里首推的模式,阿里云上有商用版本的GTS(Global Transaction Service 全局事务服务)
2.1、Seata的三大角色
TC(Transaction Coordinator) - 事务协调者
维护全局和分支事务的状态,驱动全局事务提交或回滚
TM(Transaction Manager) - 事务管理器
RM(Resource) - 资源管理器
管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
其中,TC为单独部署的Server服务端,TM和RM为嵌入到应用中的Client客户端。
2.2、AT(auto transcation)模式
AT模式是一种无侵入的分布式事务解决方案
阿里的seata框架,实现了该模式
在AT模式下,用户只需关注自己的“业务SQL”,用户的“业务SQL”作为第一阶段,Seata框架会自动生成事务的二阶段提交和回滚操作。
AT模式如何做到对业务的无侵入:
- 一阶段
在一阶段中,Seata会拦截“业务SQL
”,首先解析SQL语义,找到“业务SQL要更新的业务数据,在业务数据被更新前,将其保存成“before image
",然后执行”业务SQL“更新业务数据,在业务数据更新之后,再将其保存成”after image
“,最后生成行锁
,以上操作全部在一个数据库事务内完成,这样保证了一阶段操作的原子性。
- 二阶段提交
二阶段如果是提交的话,因为业务“SQL”在一阶段已经提交至数据库,所以Seata框架只需将一阶段保存的快照数据和行锁进行删掉,完成数据清理即可。
- 二阶段回滚:
二阶段如果是回滚的话,Seata就需要一阶段已经执行的“业务SQL”,还原业务数据,回滚方式便是用“before image"还原业务数据;但在还原前要首先要校验脏写,对比数据库当前业务数据和after image,如果两份数据一致就说明没有脏写,可以还原数据,如果不一致就说明有脏写需要人工干预处理。
2.3、TCC模式
- 侵入性强,并且得自己实现相关事务控制逻辑
- 整个过程中基本没有锁,性能更强
TCC模式需要用户根据自己的业务场景实现Try
,Confirm
和Cancel
三个操作;事务发起方在一阶段执行try方式,在二阶段提交执行Contirm方法;二阶段回滚执行Cancel方法。
2.4、Saga模式
Saga模式是SEATA提供的长事务解决方案,在Saga模式中,业务流程中每个参与者都提交本地事务,当出现某一个参与者失败则补偿前面已经成功的参与者,一阶段正向服务和二阶段补偿服务都由业务开发实现。
2.5、XA模式
前提
- 支持XA 事务的数据库。
- Java 应用,通过 JDBC 访问数据库。
整体机制
在 Seata 定义的分布式事务框架内,利用事务资源(数据库、消息服务等)对 XA 协议的支持,以 XA 协议的机制来管理分支事务的一种 事务模式。
- 执行阶段:
-
- 可回滚:业务 SQL 操作放在 XA 分支中进行,由资源对 XA 协议的支持来保证 可回滚
- 持久化:XA 分支完成后,执行 XA prepare,同样,由资源对 XA 协议的支持来保证 持久化(即,之后任何意外都不会造成无法回滚的情况)
- 完成阶段:
-
- 分支提交:执行 XA 分支的 commit
- 分支回滚:执行 XA 分支的 rollback
3、Seata快速开始
3.1、Seata Server(TC)环境搭建
Server端存储模式(store.mode)支持三种:
- file : 单机模式,全局事务会话信息内存中读写并持久化本地文件root.data,性能较高(默认)
- db(5.7+) :高可用模式,全局事务会话信息通过db共享,相应性能差些
- redis : Seata-Server 1.3及以上版本支持,性能较高,存在事务信息丢失风险;请提前配置当前场景的redis持久化配置
3.1.2、db+Nacos方式部署
资源下载地址: 【1.3.0版本windows为例】
https://github.com/seata/seata/releases
1、打开config/file.conf
2、修改mode=“db”
3、修改数据库连接信息(url,username,password)
4、创建数据库(seata)
5、下载相关需要的资源
解压完成后,我们只需要要这个script
文件夹即可
将这个文件夹放入我们的steta目录(方便我们用里面的一些资源)
6、引入sql,script/server/db/mysql.sql
7、打开conf/registry.conf文件进行修改
registry部分:
config部分:
8、修改script/config-center/config.txt,为了等一下导入配置
注意点:
配置的事务分组,要与客户端配置的事务分组保持一致
- 客户端properties配置:springcloud.alibaba.seata.tx-service-group=my_test_tx_troup
- default需要跟客户端和registry.conf中registry中的cluster保持一致
事务分组:异地机房停电容错机制
my_test_tx_group
可以自定义 比如(guangzhou,shanghai),对应的client也要配置
9、配置参数同步到Nacos
1、进入script/config-center/nacos
如果你的ip和端口都是默认的话,直接双击即可。否则可以使用下面的启动方式
sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t 93d7e8bc-389c-45e1-99a4-1b14a3309d4a
参数说明:
-h: nacos地址
-p: nacos端口号
-g: 配置分组,默认为SEATA_GROUP
-t: Nacos命名空间ID字段,默认为空
在git bash里面执行命令即可
10、打开nacos进行查看,所有配置成功同步
11、启动seata
找到seata/bin/seata-server.bat双击启动即可
所有启动参数
参数 | 全写 | 作用 | 备注 |
-h | –host | 指定在注册中心注册的ip | 不指定时获取当前ip,外部访问部署建议指定 |
-p | –port | 指定server启动的端口 | 默认8091 |
-m | –storeMode | 事务日志存储方式 | 支持file,db,redis,默认为file,注意:redis需seata-server1.3版本及以上 |
-n | –serverNode | 用户指定seata-server节点id | 如1,2,3默认为1 |
-e | –seataEnv | 指定seata-server运行环境 | 如dev,test,服务启动会使用registry-dev.conf这样的配置 |
例子:bin/seata-server.sh -h 127.0.0.1 -p 8091 -m db -n 1 -e tset
启动集群方式:
bin/seata-server.sh -p 8091 -n 1
bin/seata-server.sh -p 8092 -n 2
bin/seata-server.sh -p 8093 -n 3
这时候我们的steata已经进来了
3.2、分布式事务代码搭建
3.2.1、创建两个数据库
- 订单数据库
CREATE TABLE `order` (`id` bigint NOT NULL AUTO_INCREMENT COMMENT '订单id',`product_id` bigint NOT NULL COMMENT '商品id',`total_amount` int NOT NULL COMMENT '商品数量',`status` tinyint NOT NULL COMMENT '状态',PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
- 库存数据库
CREATE TABLE `stock` (`id` bigint NOT NULL AUTO_INCREMENT COMMENT '库存id',`product_id` bigint NOT NULL COMMENT '商品id',`count` bigint NOT NULL COMMENT '库存数量',PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
3.2.2、创建几个服务模块
- seata父模块
pom文件如下
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>springcloud-alibaba</artifactId><groupId>com.lili</groupId><version>0.0.1-SNAPSHOT</version></parent><packaging>pom</packaging><modules><module>seata_order</module><module>seata_stock</module></modules><modelVersion>4.0.0</modelVersion><artifactId>seata</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><!--web场景启动器--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--mysql驱动--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!--lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--mybatisPlus--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.2</version></dependency></dependencies> </project>
- seata_order子模块
pom文件如下:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>seata</artifactId><groupId>com.lili</groupId><version>0.0.1-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>seata_order</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><!--nacos 服务 注册与发现--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--添加openfeign的依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency></dependencies> </project>
yml文件:
server:port: 8888 # 服务名称 spring:application:name: order-seata-servercloud:nacos:discovery:server-addr: 101.34.254.160:8847username: nacospassword: nacosnamespace: publicdatasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/seata_order?characterEncoding=utf-8&serverTimezone=UTCusername: rootpassword: root
启动类
@EnableFeignClients @SpringBootApplication public class SeataOrderApplication {public static void main(String[] args) {SpringApplication.run(SeataOrderApplication.class,args);} }
实体类:
@Data @AllArgsConstructor @NoArgsConstructor @TableName("ll_order") public class Order implements Serializable {private static final long serialVersionUID = 1L;/*** 订单id*/@TableId(value = "id",type = IdType.AUTO)private Long id;/*** 商品id*/@TableField("product_id")private Long productId;/*** 商品数量*/@TableField("total_amount")private Integer totalAmount;/*** 状态*/@TableField("status")private Integer status; }
mapper层
@Mapper public interface OrderMapper extends BaseMapper<Order> { }
service层接口
public interface OrderService extends IService<Order> {void addOrder(); }
service层实现类
@Service public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {@AutowiredStockFeignService stockFeignService;@AutowiredOrderMapper orderMapper;@Overridepublic void addOrder(){// 模拟添加订单信息Order order = new Order();order.setStatus(0);order.setProductId(10L);order.setTotalAmount(20);// 添加订单orderMapper.insert(order);// 减少库存stockFeignService.updateStock();} }
feign下的调用库存接口
@FeignClient(value = "stock-seata-server",path = "/stock") public interface StockFeignService {@RequestMapping("/updateStock")void updateStock(); }
controller层
@RestController @RequestMapping("/order") public class OrderController {@Autowiredpublic OrderService orderService;@RequestMapping("/addOrder")public void addOrder() {orderService.addOrder();} }
- seata_stock子模块
pom文件如下:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>seata</artifactId><groupId>com.lili</groupId><version>0.0.1-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>seata_stock</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><!--nacos 服务 注册与发现--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--添加openfeign的依赖--><dependency> <groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency></dependencies> </project>
yml文件:
server:port: 9999 # 服务名称 spring:application:name: stock-seata-servercloud:nacos:discovery:server-addr: 101.34.254.160:8847username: nacospassword: nacosnamespace: publicdatasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/seata_stock?characterEncoding=utf-8&serverTimezone=UTCusername: rootpassword: root
实体类:
@Data @AllArgsConstructor @NoArgsConstructor @TableName("ll_stock") public class Stock implements Serializable {private static final long serialVersionUID = 1L;/*** 库存id*/@TableId(value = "id", type = IdType.AUTO)private Long id;/*** 商品id*/@TableField("product_id")private Long productId;/*** 库存数量*/@TableField("count")private Long count; }
mapper层
@Mapper public interface StockMapper extends BaseMapper<Stock> { }
service层接口
public interface StockService extends IService<Stock> {void updateStock(); }
service层实现类
@Service public class StockServiceImpl extends ServiceImpl<StockMapper, Stock> implements StockService {@AutowiredStockMapper stockMapper;@Overridepublic void updateStock() {// 模拟修改数据Stock stock = new Stock();stock.setId(1L);stock.setCount(900L-20L);stockMapper.updateById(stock);} }
controller层
@RestController @RequestMapping("/stock") public class StockController {@Autowiredpublic StockService stockService;@RequestMapping("/updateStock")public void updateStock(){stockService .updateStock();} }
3.3.3、使用@Translation注解测试
服务消费方
@Transactional(rollbackFor = Exception.class ) public void addOrder(){// 模拟添加订单信息Order order = new Order();order.setStatus(0);order.setProductId(10L);order.setTotalAmount(20);// 添加订单orderMapper.insert(order);// 更新库存stockFeignService.updateStock();// 测试异常int i= 1/0; }
进行调用测试
java.lang.ArithmeticException: / by zero
控制台正常报错,我们来看看数据库
订单表成功回滚,但是库存表却已经被改变了
3.3.4、整合seata(@GlobalTransactional
)
第一步,两个服务都需添加下列依赖
<!--seata依赖--> <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId> </dependency>
第二步:各微服务对应数据库中添加undo_log表:
CREATE TABLE `undo_log`(`id` bigint(20) NOT NULL AUTO_INCREMENT,`branch_id` bigint(20) NOT NULL,`xid` varchar(100) NOT NULL,`context` varchar(128) NOT NULL,`rollback_info` longblob NOT NULL,`log_status` int(11) NOT NULL,`log_created` datetime NOT NULL,`log_modified` datetime NOT NULL,PRIMARY KEY (`id`),UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`) )ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
第三步:
配置事务的分组,这个要与前面设置的分组相对应(两个服务都需要配置)
spring:cloud:alibaba:seata:tx-service-group: my_test_tx_group
配置seata的注册中心和配置中心(两个服务都需配置)
#配置seata的注册中心,告诉seata client怎么去访问seate server(TC) seata:registry:type: nacosnacos:server-addr: 101.34.254.160:8847 #seate server所在的nacos服务地址application: seata-server #seate server 的服务名username: nacospassword: nacosgroup: SEATA_GROUP # seate server 所在的组,默认就是SEATA_GROUP,没有改可以不用配置config: # 配置中心type: nacosnacos:server-addr: 101.34.254.160:8847username: nacospassword: nacosgroup: SEATA_GROUP# 如果是默认空间则可以不用添加namespace: 93d7e8bc-389c-45e1-99a4-1b14a3309d4a
最后,方法上加上@GlobalTransaction
注解,重新测试
@GlobalTransactional public void addOrder(){// 模拟添加订单信息Order order = new Order();order.setStatus(0);order.setProductId(10L);order.setTotalAmount(20);// 添加订单orderMapper.insert(order);// 减少库存stockFeignService.updateStock();// 测试异常int i= 1/0; }
运行保存后,发现我们的数据成功回滚,分布式事务到这里已经完全配置成功了。
相关文章:

SpringCloudAliBaba篇之Seata:分布式事务组件理论与实践
1、事务简介 事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。在关系数据库中,一个事务由一组SQL语句组成,事务具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID原则。 原子性(atomici…...

在centos7.9上安装Jenkins的安装过程
1.jenkins的安装和配置: 安装JDK: yum install -y fontconfig java-11-openjdk # 安装目录:/usr/lib/jvm # fontconfig 是 Linux 系统中用于配置和管理字体的一种工具 下载jenkins安装包: sudo wget -O /etc/yum.repos.d/jenkins…...
uni-app基本标签
导航栏设置 - navigationBarBackgroundColor: 设置导航栏的背景颜色(全局页面) - navigationBarTextStyle: 导航栏标题颜色(仅支持 black 和 white) - navigationBarTitleText: 设置导航栏标题内容 - enablePullDownRefresh: 是否…...

《PySpark大数据分析实战》-14.云服务模式Databricks介绍基本概念
📋 博主简介 💖 作者简介:大家好,我是wux_labs。😜 热衷于各种主流技术,热爱数据科学、机器学习、云计算、人工智能。 通过了TiDB数据库专员(PCTA)、TiDB数据库专家(PCTP…...

微信小程序校园跑腿系统怎么做,如何做,要做多久
在这个互联网快速发展、信息爆炸的时代,人人都离不开手机,每个人都忙于各种各样的事情,大学生也一样,有忙于学习,忙于考研,忙着赚学分,忙于参加社团,当然也有忙于打游戏的&#x…...

当我分别问8款GPT一个问题。。。
前两天下班在地铁上无聊寻思问一下不同的GPT一个相同的问题,哪个会给出我比较满意的答案,然后我就提问:我老妹有点憨怎么办?(ps:开玩笑的,嘻嘻。。。) 很明显其他GPT都给出了大差不差…...
Elasticsearch 8.9 search命令执行查询源码
一、相关的API的handler1、接收HTTP请求的handler2、往数据节点发送查询请求的action(TransportSearchAction)3、通过transportService把查询请求发送到指定的数据节点 二、数据节点收到请求的处理逻辑1、尝试从缓存中加载查询结果2、不通过缓存查询,直接执行查询(1…...
【PHP】身份证正则验证、校验位验证
目录 1.正则 简单正则 详细正则 2.校验位验证 1.正则 简单正则 function isValidIdCardNumber($idCardNumber) {// 身份证号长度为 15 位或 18 位$pattern /^(?:\d{15}|\d{17}[\dxX])$/;return preg_match($pattern, $idCardNumber); }$idCardNumber 12345678901234567…...

Matlab示例-Examine 16-QAM Using MATLAB学习笔记
工作之余学习16-QAM 写在前面 网上看到许多示例,但一般都比较难以跑通。所以,还是老方法,先将matlab自带的例子研究下。 Examine 16-QAM Using MATLAB Examine 16-QAM Using MATLAB 或者,在matlab中,键入&#x…...
ArcGIS Pro SDK运行消息只提示一次
工具大部分都是异步执行,所以提示信息需要异步执行完再进行,所以注意async和await的使用。 相关async和await的文章请查看C# 彻底搞懂async/await_c# async await-CSDN博客 public async Task InformationPrompt() {string message String.Empty;await ArcGIS.De…...

通话状态监听-Android13
通话状态监听-Android13 1、Android Telephony 模块结构2、监听和广播获取通话状态2.1 注册2.2 通话状态通知2.3 通话状态 3、通知状态流程* 关键日志 frameworks/base/core/java/android/telephony/PhoneStateListener.java 1、Android Telephony 模块结构 Android Telephony…...

无懈可击的防泄密之旅:迅软DSE在民营银行的成功实践
客户简要介绍 某股份有限公司主体是中部地区的民营银行,由其母公司联合9家知名民营企业共同发起设立。正式开业于2016年,紧紧围绕目标产业生态圈和消费金融,着力打造产业银行、便捷银行、数字银行、财富管理银行为一体的BEST银行,…...

【送书活动】智能汽车、自动驾驶、车联网的发展趋势和关键技术
文章目录 前言01 《智能汽车》推荐语 02 《SoC底层软件低功耗系统设计与实现》推荐语 03 《SoC设计指南》推荐语 05 《智能汽车网络安全权威指南(上册)》推荐语 06 《智能汽车网络安全权威指南(下册)》推荐语 后记赠书活动 前言 …...

不同版本QT使用qmake时创建QML项目的区别
不同版本QT使用qmake时创建QML项目的区别 文章目录 不同版本QT使用qmake时创建QML项目的区别一、QT5新建QML项目1.1 目录结构1.2 .pro 文件内容1.3 main.cpp1.4 main.qml 二、QT6新建QML项目2.1 目录结构2.2 .pro文件内容2.3 main.cpp2.4 main.qml 三、两个版本使用资源文件的区…...

【PHP入门】1.1-PHP初步语法
-PHP语法初步- PHP是一种运行在服务器端的脚本语言,可以嵌入到HTML中。 1.1.1PHP代码标记 在PHP历史发展中,可以使用多种标记来区分PHP脚本 ASP标记: <% php代码 %>短标记: <? Php代码 ?>,以上两种…...

如何在jenkins容器中安装python+httprunner+pytest+git+allure(一)
背景: API接口自动化使用python语言实现,利用httprunner框架编写自动化用例场景(执行的时候还是依赖pytest),使用jenkins自动构建git上的源代码,并产生allure报告可视化展示API执行结果。 步骤 1.进入jenkins容器 注意使用roo…...
Android终端模拟器Termux上使用Ubuntu
Termux 上安装各种 Linux 系统是通过 proot-distro 工具来实现的,所以先安装一下 proot-distro 工具。 ~ $ pkg install proot-distro 查看Termux支持安装那些Linux ~ $ proot-distro listSupported distributions:* Alpine LinuxAlias: alpineInstalled: noComme…...

【神器】wakatime代码时间追踪工具
文章目录 wakatime简介支持的IDE安装步骤API文档插件费用写在最后 wakatime简介 wakatime就是一个IDE插件,一个代码时间追踪工具。可自动获取码编码时长和度量指标,以产生很多的coding图形报表。这些指标图形可以为开发者统计coding信息,比如…...

UML统一建模语言
一、建模语言的背景: 通俗地阐述就是:客户一开始不知道要什么,开发通过客户的阐述进行理解和分析,这个过程中间可能会产生一些误解。为了避免此类事件,所以需要建模。类似于要建造一栋楼,建筑设计师根据住…...
Linux命令行控制小米电源开关
飞灵科技产品 flyelf-tech.com,flyelf.taobao.com 最近有需求通过命令控制局域网内小米电源开关,以便于写脚本对产品进行反复上电的启动测试。参考了这篇文章:https://blog.csdn.net/2301_77209380/article/details/129797846 获取小米设备的…...

简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...

ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...

springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)
目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...

Chrome 浏览器前端与客户端双向通信实战
Chrome 前端(即页面 JS / Web UI)与客户端(C 后端)的交互机制,是 Chromium 架构中非常核心的一环。下面我将按常见场景,从通道、流程、技术栈几个角度做一套完整的分析,特别适合你这种在分析和改…...