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特性是数据库直接提供支持。本地事务应用架构如下所示:

image

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框架会自动生成事务的二阶段提交和回滚操作。

image

AT模式如何做到对业务的无侵入:

  • 一阶段

在一阶段中,Seata会拦截“业务SQL”,首先解析SQL语义,找到“业务SQL要更新的业务数据,在业务数据被更新前,将其保存成“before image",然后执行”业务SQL“更新业务数据,在业务数据更新之后,再将其保存成”after image“,最后生成行锁,以上操作全部在一个数据库事务内完成,这样保证了一阶段操作的原子性。

image

  • 二阶段提交

二阶段如果是提交的话,因为业务“SQL”在一阶段已经提交至数据库,所以Seata框架只需将一阶段保存的快照数据和行锁进行删掉,完成数据清理即可。

image

  • 二阶段回滚:

二阶段如果是回滚的话,Seata就需要一阶段已经执行的“业务SQL”,还原业务数据,回滚方式便是用“before image"还原业务数据;但在还原前要首先要校验脏写,对比数据库当前业务数据和after image,如果两份数据一致就说明没有脏写,可以还原数据,如果不一致就说明有脏写需要人工干预处理。

image

2.3、TCC模式

  • 侵入性强,并且得自己实现相关事务控制逻辑
  • 整个过程中基本没有锁,性能更强

TCC模式需要用户根据自己的业务场景实现Try,ConfirmCancel三个操作;事务发起方在一阶段执行try方式,在二阶段提交执行Contirm方法;二阶段回滚执行Cancel方法。

image

2.4、Saga模式

Saga模式是SEATA提供的长事务解决方案,在Saga模式中,业务流程中每个参与者都提交本地事务,当出现某一个参与者失败则补偿前面已经成功的参与者,一阶段正向服务和二阶段补偿服务都由业务开发实现。

image

2.5、XA模式

前提

  • 支持XA 事务的数据库。
  • Java 应用,通过 JDBC 访问数据库。

整体机制

在 Seata 定义的分布式事务框架内,利用事务资源(数据库、消息服务等)对 XA 协议的支持,以 XA 协议的机制来管理分支事务的一种 事务模式。

image

  • 执行阶段:
    • 可回滚:业务 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、下载相关需要的资源

image

解压完成后,我们只需要要这个script文件夹即可

image

将这个文件夹放入我们的steta目录(方便我们用里面的一些资源)

image

6、引入sql,script/server/db/mysql.sql

image

7、打开conf/registry.conf文件进行修改

registry部分:

image

config部分:

image

8、修改script/config-center/config.txt,为了等一下导入配置

image

注意点:

配置的事务分组,要与客户端配置的事务分组保持一致

image

  • 客户端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

image

如果你的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里面执行命令即可

image

10、打开nacos进行查看,所有配置成功同步

image

11、启动seata

找到seata/bin/seata-server.bat双击启动即可

image

所有启动参数

参数全写作用备注
-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已经进来了

image

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;

image

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-server
  cloud:
    nacos:
      discovery:
        server-addr: 101.34.254.160:8847
        username: nacos
        password: nacos
        namespace: public
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/seata_order?characterEncoding=utf-8&serverTimezone=UTC
    username: root
    password: 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 {
    @Autowired
    StockFeignService stockFeignService;
    @Autowired
    OrderMapper orderMapper;
    @Override
    public 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 {
    @Autowired
    public 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-server
  cloud:
    nacos:
      discovery:
        server-addr: 101.34.254.160:8847
        username: nacos
        password: nacos
        namespace: public
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/seata_stock?characterEncoding=utf-8&serverTimezone=UTC
    username: root
    password: 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 {
    @Autowired
    StockMapper stockMapper;
    @Override
    public void updateStock() {
        // 模拟修改数据
        Stock stock = new Stock();
        stock.setId(1L);
        stock.setCount(900L-20L);
        stockMapper.updateById(stock);
    }
}

controller层

@RestController
@RequestMapping("/stock")
public class StockController {
    @Autowired
    public 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

控制台正常报错,我们来看看数据库

image

订单表成功回滚,但是库存表却已经被改变了

image

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: nacos
    nacos:
      server-addr: 101.34.254.160:8847  #seate server所在的nacos服务地址
      application: seata-server #seate server 的服务名
      username: nacos
      password: nacos
      group: SEATA_GROUP # seate server 所在的组,默认就是SEATA_GROUP,没有改可以不用配置
  config: # 配置中心
    type: nacos
    nacos:
      server-addr: 101.34.254.160:8847
      username: nacos
      password: nacos
      group: 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;
}

运行保存后,发现我们的数据成功回滚,分布式事务到这里已经完全配置成功了。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

开源学习项目推荐

文章目录 koodo-reader凤凰架构学习项目NPS 内网穿透客户端 koodo-reader 项目地址&#xff1a;https://github.com/koodo-reader/koodo-reader 介绍&#xff1a;一个开源的阅读器&#xff0c;阅读pdf也有目录&#xff0c;作为epub阅读器和pdf阅读器看资料挺好 凤凰架构 项…

前端视角看 Docker :在国内的基础配置教程(含国内镜像源)

引言 在国内使用Docker时&#xff0c;直接从Docker Hub拉取镜像可能会遇到网络速度慢的问题。配置国内的镜像加速器可以显著提升拉取速度。本教程将指导您完成安装Docker后的基础配置&#xff0c;特别是设置国内镜像加速器。 1. 安装Docker 确保您已在系统上安装Docker。根…

基于Tkinter制作简易的CAN bootloader上位机

文章目录 1.前言2.测试设备3.上位机3.1 参考资料3.2 上位机主要功能3.3 上位机发送流程 升级测试例程分享 1.前言 之前基于S32K144EVB和Tkinter编写了一个简易的串口bootloader上位机&#xff0c;链接如下&#xff1a; 基于Tkinter制作简易的串口bootloader上位机 (qq.com) …

归一化和标准化(Z-Score)

在处理数据过程中&#xff0c;通常会有不同规格的数据&#xff0c;比如年龄的取值范围是0-130&#xff0c;收入的取值范围是0-100000等等&#xff0c;如果不进行归一化或标准化处理&#xff0c;梯度下降每次走过的相对长度就不一样&#xff0c;就导致某个参数很快就找到了最优解…

如何预防[[MyFile@waifu.club]].wis [[backup@waifu.club]].wis勒索病毒感染您的计算机?

导言&#xff1a; 近期&#xff0c;一种新兴的威胁[[MyFilewaifu.club]].wis [[backupwaifu.club]].wis勒索病毒&#xff0c;引起了广泛关注。这种恶意软件通过其高度复杂的加密算法&#xff0c;威胁着用户和组织的数据安全。本文将深入介绍[[MyFilewaifu.club]].wis [[backup…

Linux软件管理rpm和yum

rpm方式管理 rpm软件包名称: 软件名称 版本号(主版本、次版本、修订号) 操作系统 -----90%的规律 #有依赖关系,不能自动解决依赖关系。 举例&#xff1a;openssh-6.6.1p1-31.el7.x86_64.rpm 数字前面的是名称 数字是版本号&#xff1a;第一位主版本号&#xff0c;第二位次版本…

【ArkTS】路由传参

传参 使用router.pushUrl()&#xff0c;router.push()官方不推荐再使用了。 格式&#xff1a; router.pushUrl({url: 路由地址,params:{参数名&#xff1a;值} )跳转时需要注意路由表中是否包含路由地址。 路由表路径&#xff1a; entry > src > main > resources &g…

使用vite搭建项目时,在启动vite后,浏览器显示页面:找不到localhost的网页

现象 在使用前端工具vite&#xff08;版本5&#xff09;&#xff0c;搭建vue3项目时&#xff0c;启动vite&#xff0c;浏览器显示页面&#xff1a;找不到localhost的网页, 起初怀疑是 未加参数 --host0.0.0.0,导致&#xff0c;后加上该参数后问题依旧 解决 将index.html页面…

Python框架篇(6):FastApi-配置管理

提示: 微信搜索【猿码记】回复 【fastapi】即可获取源码信息~ 在这一篇文章中,对fastapi框架和pydantic进行了升级&#xff0c;然后就是各种不兼容&#xff0c;以后再也不敢轻易升级.... pydantic&#xff1a;从 1.10.11升级到 2.5.2&#xff0c;这里有坑&#xff0c;里面有很多…

GitBook安装及使用——使用 Markdown 创建你自己的博客网站和电子书

目录 前言一、依赖环境二.gitbook安装使用1.安装 gitbook-cli2.安装 gitbook3.Gitbook初始化4.创建你的文章5.修改 SUMMARY.md 和 README.md6.编译生成静态网页7.运行以便在浏览器预览8.运行效果 前言 GitBook是一个命令行工具&#xff0c;用于使用 Markdown 构建漂亮的博客网…

Temu、Shein、OZON测评自养号,IP和指纹浏览器的优缺点分析

随着全球电子商务的飞速发展&#xff0c;跨境电商环境展现出巨大的潜力和机遇。然而&#xff0c;跨境卖家们也面临着更激烈的竞争、更严格的规定和更高的运营成本等挑战。为了在这个环境中脱颖而出&#xff0c;一些卖家尝试使用自动脚本程序进行浏览和下单。然而&#xff0c;这…

双非大数据

双非本秋招上岸总结 个人简介 学历&#xff1a;双非&#xff1b; 专业&#xff1a;软件工程&#xff1b; 求职岗位&#xff1a;大数据开发工程师&#xff1b; 状态&#xff1a;已上岸 翻车经历 学校以Java后端开发为主流&#xff0c;我从大二开始学习Java&#xff0c;直到大四…

Navicat关闭自动检查更新版本教程

Navicat关闭自动检查更新版本教程 首先&#xff0c;点击菜单中的工具菜单&#xff0c;弹出了下拉菜单选中为选项点击选项 首先&#xff0c;点击菜单中的工具菜单&#xff0c;弹出了下拉菜单选中为选项 点击选项 去掉勾选上在启动时自动检查更新选项

【lesson19】MySQL内置函数(2)数学函数和其它函数

文章目录 数学函数函数使用 其它函数函数使用 数学函数 函数使用 其它函数 函数使用 user() 查询当前用户 database()显示当前正在使用的数据库 password()函数&#xff0c;MySQL数据库使用该函数对用户加密 md5(str)对一个字符串进行md5摘要&#xff0c;摘要后得到一个32…

定制 Electron 窗口标题栏

Electron 是一款流行的桌面应用开发框架&#xff0c;基于 Web 技术构建&#xff0c;提供了强大的跨平台能力。在开发过程中&#xff0c;经常需要定制窗口标题栏以创造独特的用户体验。 1. 完全隐藏默认标题栏 有时候&#xff0c;我们希望创建一个自定义的标题栏&#xff0c;完…

前端做表格导出

下面来介绍一下方法 在vue页面里写调用方法 //表头数据格式 column: [{ key: Photo, width: 70, height: 50, colWidth: 100, title: 图片, type: image },{ key: Name, colWidth: , title: 名称, type: text },{ key: Phone, colWidth: , title: 手机号, type: text },{key:…

时尚炫酷动态图文幻灯片视频素材AE模板

这个After Effects模板以时尚和动态幻灯片为特色。可以编辑和自定义文本占位符、媒体占位符和颜色。用来展示照片或视频剪辑。不需要任何插件。 来自AE模板网&#xff1a;https://aemuban.com/28093.html

Shell脚本与计划任务

1.确定备份方案 为了顺利完成上述备份方案&#xff0c;首先授权用户能够查询studydb、coursedb库。 针对本案例的情况&#xff0c;可以创建一个专用的数据库备份账户operator&#xff0c;允许从备份主机 172.16.16.220连接到MySOL数据库.并授予对studydb.coursedb库的读取权限…

晶体管的工作状态判断和工作条件

晶体管是模拟电路中基础的器件&#xff0c;对于电子工程师来说&#xff0c;了解晶体管工作的条件和判断晶体管的工作状态都是非常基础的&#xff0c;本文将带大家一起学习或回顾一下。 一、晶体管工作的条件 1.集电极电阻Rc&#xff1a; 在共发射极电压放大器中&#xff0c;…

leetcode 450. 删除二叉搜索树中的节点

leetcode 450. 删除二叉搜索树中的节点 题目 给定一个二叉搜索树的根节点 root 和一个值 key&#xff0c;删除二叉搜索树中的 key 对应的节点&#xff0c;并保证二叉搜索树的性质不变。返回二叉搜索树&#xff08;有可能被更新&#xff09;的根节点的引用。 一般来说&#x…