当前位置: 首页 > news >正文

【SpringCloud20】SpringCloud Alibaba Seata处理分布式事务

目录

  • 1.分布式事务问题
  • 2.Seata简介
    • 2.1 是什么
    • 2.2 作用
    • 2.3 下载
    • 2.4 如何使用
  • 3.Seata-Server安装
    • 3.1 下载网址
    • 3.2 下载版本
    • 3.3 seata解压到指定目录并修改文件
      • 3.3.1 nacos新增配置文件
      • 3.3.2 修改application.yml
    • 3.4 数据库新建seata
    • 3.5 在seata里建表
    • 3.6 启动Nacos端口号8848
    • 3.7 启动seata-server
  • 4.订单/库存/账户业务数据库准备
    • 4.1 分布式事务业务说明
    • 4.2 创建业务数据库
    • 4.3 按照上述3库分别建对应业务表
    • 4.4 按照上述3库分别建对应的回滚日志
    • 4.5 最终效果
  • 5.订单/库存/账户业务微服务准备
    • 5.1 业务需求
    • 5.2 新建Order-Module
      • 5.2.1 新建seata-order-service2001
      • 5.2.2 POM
      • 5.2.3 YML
      • 5.2.4 修改seata路径下的/conf/application.yml
      • 5.2.6 遇到的问题和坑
      • 5.2.7 domain
      • 5.2.8 Dao接口及实现
      • 5.2.9 Service接口及实现
      • 5.2.10 Conrtoller
      • 5.2.10 Config配置
      • 5.2.11 主启动
    • 5.3 新建Storage-Module
      • 5.3.1 新建seata-storage-service2002
      • 5.3.2 POM
      • 5.3.3 YML
      • 5.3.4 修改seata路径下的/conf/application.yml
      • 5.3.5 domain
      • 5.3.6 Dao接口及实现
      • 5.3.7 Service接口及实现
      • 5.3.8 Conrtoller
      • 5.3.9 Config配置
      • 5.3.10 主启动
    • 5.4 新建Account-Module
      • 5.4.1 新建seata-account-service2003
      • 5.4.2 POM
      • 5.4.3 YML
      • 5.4.4 修改seata路径下的/conf/application.yml
      • 5.4.5 domain
      • 5.4.6 Dao接口及实现
      • 5.4.7 Service接口及实现
      • 5.4.8 Conrtoller
      • 5.4.9 Config配置
      • 5.4.10 主启动
  • 6.测试
    • 6.1数据库初始情况
    • 6.2 正常下单
    • 6.3 超时异常,没加@GlobalTransactional
    • 6.4 超时异常,添加@GlobalTransactional
  • 7.补充
    • 7.1 Seata
    • 7.2 再看TC/TM/RM三大组件
    • 7.3 AT模式如何做到对业务的无侵入
      • 7.3.1 是什么
      • 7.3.2 一阶段加载
      • 7.3.3 正常情况二阶段提交
      • 7.3.4 异常情况二阶段回滚
    • 7.4 debug
    • 7.5 补充

1.分布式事务问题

分布式前

  • 单机单库没有这个问题
  • 从1:1到1:N到N:N

分布式后
单体应用被拆分成微服务应用,原来的三个模块被拆分成三个独立的应用,分别使用三个独立的数据元

业务操作需要调用三个服务来完成,此时每个服务内部的数据一致性由本地事务来保证,但是全局的数据的一致性问题没法保证

概述:一次业务操作需要跨多个数据源或需要跨多系统进行远程调用,就会产生分布式问题

在这里插入图片描述

2.Seata简介

2.1 是什么

官网
Seata 是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务。在 Seata 开源之前,其内部版本在阿里经济体内部一直扮演着应用架构层数据一致性的中间件角色,帮助经济体平稳的度过历年的双11,对上层业务进行了有力的技术支撑。

2.2 作用

Seata是一个典型的分布式事务过程

分布式事务处理过程的一致性的一ID+三组件模型
一ID: Transaction ID XID 全局唯一的事务ID
三组件概念:
TC (Transaction Coordinator) - 事务协调器,维护全局事务的运行状态,负责协调并驱动全局事务的提交或回滚

TM (Transaction Manager) - 控制全局事务的边界,负责开启一个全局事务,并最终发起全局提交或全局回滚的决议

RM (Resource Manager) - 控制分支事务,负责分支注册、状态汇报,并接收事务协调器的指令,驱动分支(本地)事务的提交和回滚

在这里插入图片描述

处理过程

  1. TM 向 TC 申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的 XID;

  2. XID 在微服务调用链路的上下文中传播;

  3. RM 向 TC 注册分支事务,将其纳入 XID 对应全局事务的管辖;

  4. TM 向 TC 发起针对 XID 的全局提交或回滚决议;

  5. TC 调度 XID 下管辖的全部分支事务完成提交或回滚请求。

在这里插入图片描述

2.3 下载

下载网址

2.4 如何使用

本地@Transactional
全局@GlobalTransactional
SEATA分分布式交易解决方案
在这里插入图片描述

3.Seata-Server安装

3.1 下载网址

下载网址

3.2 下载版本

3.3 seata解压到指定目录并修改文件

3.3.1 nacos新增配置文件

nacos中新建命名空间
在这里插入图片描述

在nacos中添加配置

  • Data Id = seataServer.properties
  • Group = SEATA_GROUP
store.mode=db
store.lock.mode=db
store.session.mode=dbstore.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.cj.jdbc.Driver
store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true&rewriteBatchedStatements=true
store.db.user=root
store.db.password=123456
store.db.minConn=5
store.db.maxConn=30
store.db.globalTable=global_table
store.db.branchTable=branch_table
store.db.distributedLockTable=distributed_lock
store.db.queryLimit=100
store.db.lockTable=lock_table
store.db.maxWait=5000service.vgroupMapping.fsp_tx_group=default

3.3.2 修改application.yml

拷贝一份application.yml
修改application.yml如下

server:port: 7091spring:application:name: seata-serverlogging:config: classpath:logback-spring.xmlfile:path: ${user.home}/logs/seata
#  extend:
#    logstash-appender:
#      destination: 127.0.0.1:4560
#    kafka-appender:
#      bootstrap-servers: 127.0.0.1:9092
#      topic: logback_to_logstashconsole:user:username: seatapassword: seataseata:config:# support: nacos, consul, apollo, zk, etcd3type: nacosnacos:serverAddr: 127.0.0.1:8848namespace: #修改为自己的group: SEATA_GROUP #需要与前面创建的配置文件相对应username: nacospassword: nacosfile-extension: yamlshared-configs:- dataId: seata-server.yaml #需要与前面创建的配置文件相对应namespace: 6f25df50-1e22-4301-9587-d627b6158fc9 #修改为自己的group: SEATA_GROUPregistry:# support: nacos, eureka, redis, zk, consul, etcd3, sofatype: nacosnacos:serverAddr: 127.0.0.1:8848namespace: #修改为自己的group: SEATA_GROUPusername: nacospassword: nacosfile-extension: yamlshared-configs:- dataId: seata-server.yaml #需要与前面创建的配置文件相对应namespace: 6f25df50-1e22-4301-9587-d627b6158fc9 #需要与前面创建的配置文件相对应group: SEATA_GROUP #需要与前面创建的配置文件相对应#store:# support: file 、 db 、 redis#mode: file
#  server:
#    service-port: 8091 #If not configured, the default is '${server.port} + 1000'security:secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017tokenValidityInMilliseconds: 1800000ignore:urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/api/v1/auth/login

3.4 数据库新建seata

如果是mysql8参考,用seata1.3.0可以用seata0.9.0不行链接
在这里插入图片描述

3.5 在seata里建表

-- -------------------------------- The script used when storeMode is 'db' --------------------------------
-- the table to store GlobalSession data
CREATE TABLE IF NOT EXISTS `global_table`
(`xid`                       VARCHAR(128) NOT NULL,`transaction_id`            BIGINT,`status`                    TINYINT      NOT NULL,`application_id`            VARCHAR(32),`transaction_service_group` VARCHAR(32),`transaction_name`          VARCHAR(128),`timeout`                   INT,`begin_time`                BIGINT,`application_data`          VARCHAR(2000),`gmt_create`                DATETIME,`gmt_modified`              DATETIME,PRIMARY KEY (`xid`),KEY `idx_status_gmt_modified` (`status` , `gmt_modified`),KEY `idx_transaction_id` (`transaction_id`)
) ENGINE = InnoDBDEFAULT CHARSET = utf8mb4;-- the table to store BranchSession data
CREATE TABLE IF NOT EXISTS `branch_table`
(`branch_id`         BIGINT       NOT NULL,`xid`               VARCHAR(128) NOT NULL,`transaction_id`    BIGINT,`resource_group_id` VARCHAR(32),`resource_id`       VARCHAR(256),`branch_type`       VARCHAR(8),`status`            TINYINT,`client_id`         VARCHAR(64),`application_data`  VARCHAR(2000),`gmt_create`        DATETIME(6),`gmt_modified`      DATETIME(6),PRIMARY KEY (`branch_id`),KEY `idx_xid` (`xid`)
) ENGINE = InnoDBDEFAULT CHARSET = utf8mb4;-- the table to store lock data
CREATE TABLE IF NOT EXISTS `lock_table`
(`row_key`        VARCHAR(128) NOT NULL,`xid`            VARCHAR(128),`transaction_id` BIGINT,`branch_id`      BIGINT       NOT NULL,`resource_id`    VARCHAR(256),`table_name`     VARCHAR(32),`pk`             VARCHAR(36),`status`         TINYINT      NOT NULL DEFAULT '0' COMMENT '0:locked ,1:rollbacking',`gmt_create`     DATETIME,`gmt_modified`   DATETIME,PRIMARY KEY (`row_key`),KEY `idx_status` (`status`),KEY `idx_branch_id` (`branch_id`),KEY `idx_xid_and_branch_id` (`xid` , `branch_id`)
) ENGINE = InnoDBDEFAULT CHARSET = utf8mb4;CREATE TABLE IF NOT EXISTS `distributed_lock`
(`lock_key`       CHAR(20) NOT NULL,`lock_value`     VARCHAR(20) NOT NULL,`expire`         BIGINT,primary key (`lock_key`)
) ENGINE = InnoDBDEFAULT CHARSET = utf8mb4;INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('AsyncCommitting', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryCommitting', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryRollbacking', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('TxTimeoutCheck', ' ', 0);

3.6 启动Nacos端口号8848

在这里插入图片描述

3.7 启动seata-server

在这里插入图片描述

4.订单/库存/账户业务数据库准备

以下演示都需要先启动Nacos后启动Seata
如果Seata没启动会报错no available server to connect
在这里插入图片描述

4.1 分布式事务业务说明

业务说明
这里我们创建三个服务,一个订单服务,一个库存服务,一个账户服务

当用户下单时,会在订单服务中创建一个订单,然后通过远程调用库存服务来扣减下单商品的库存,再通过远程调用账户服务来扣减用户账户里面的余额,最后再订单服务中修改订单状态为已完成。

该操作跨越三个数据库,有两次远程调用,很明显有分布式事务问题。

三步走:

  1. 下订单
  2. 扣库存
  3. 减账户余额

4.2 创建业务数据库

  • seata_order:存储订单的数据库
  • seata_storage:存储库存的数据库
  • seata_account:存储账户信息的数据库

建库SQL
CREATE DATABASE seata_order;
CREATE DATABASE seata_storage;
CREATE DATABASE seata_account;
在这里插入图片描述

4.3 按照上述3库分别建对应业务表

seata_order库下建t_order表

CREATE TABLE t_order (`id` BIGINT ( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY,`user_id` BIGINT ( 11 ) DEFAULT NULL COMMENT '用户id',`product_id` BIGINT ( 11 ) DEFAULT NULL COMMENT '产品id',`count` INT ( 11 ) DEFAULT NULL COMMENT '数量',`money` DECIMAL ( 11, 0 ) DEFAULT NULL COMMENT '金额',
`status` INT ( 1 ) DEFAULT NULL COMMENT '订单状态:0:创建中;1:已完结' 
) ENGINE = INNODB AUTO_INCREMENT = 7 DEFAULT CHARSET = utf8;SELECT * FROM t_order;

seata_storage库下建t_storage表

CREATE TABLE t_storage (`id` BIGINT ( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY,`product_id` BIGINT ( 11 ) DEFAULT NULL COMMENT '产品id',`total` INT ( 11 ) DEFAULT NULL COMMENT '总库存',`used` INT ( 11 ) DEFAULT NULL COMMENT '已用库存',
`residue` INT ( 11 ) DEFAULT NULL COMMENT '剩余库存' 
) ENGINE = INNODB AUTO_INCREMENT = 2 DEFAULT CHARSET = utf8;INSERT INTO seata_storage.t_storage ( `id`, `product_id`, `total`, `used`, `residue` )
VALUES( '1', '1', '100', '0', '100' );SELECT * FROM t_storage;

seata_account库下建t_account表

CREATE TABLE t_account (`id` BIGINT ( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 'id',`user_id` BIGINT ( 11 ) DEFAULT NULL COMMENT '用户id',`total` DECIMAL ( 10, 0 ) DEFAULT NULL COMMENT '总额度',`used` DECIMAL ( 10, 0 ) DEFAULT NULL COMMENT '已用余额',
`residue` DECIMAL ( 10, 0 ) DEFAULT '0' COMMENT '剩余可用额度' 
) ENGINE = INNODB AUTO_INCREMENT = 2 DEFAULT CHARSET = utf8;INSERT INTO seata_account.t_account ( `id`, `user_id`, `total`, `used`, `residue` )
VALUES( '1', '1', '1000', '0', '1000' );SELECT * FROM t_account;

4.4 按照上述3库分别建对应的回滚日志

订单-库存-账户三个库下都需要个自己的回滚日志表

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,`ext` VARCHAR ( 100 ) DEFAULT NULL,PRIMARY KEY ( `id` ),
UNIQUE KEY `ux_undo_log` ( `xid`, `branch_id` ) 
) ENGINE = INNODB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8;

4.5 最终效果

在这里插入图片描述

5.订单/库存/账户业务微服务准备

5.1 业务需求

  1. 下订单
  2. 减库存
  3. 扣余额
  4. 改订单状态

5.2 新建Order-Module

5.2.1 新建seata-order-service2001

5.2.2 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"><modelVersion>4.0.0</modelVersion><parent><groupId>com.atguigu.springcloud</groupId><artifactId>cloud2022</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>seata-order-service2001</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><!--分布式事务 --><!--移除alibaba-seata自带的seata-spring-boot-starter,因为自带的版本太低 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId><exclusions><exclusion><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId></exclusion><exclusion><groupId>io.seata</groupId><artifactId>seata-all</artifactId></exclusion></exclusions></dependency><!--添加seata-spring-boot-starter依赖,版本需要与服务端版本相对应,此版本使用1.5.2 --><dependency><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId><version>1.5.2</version></dependency><dependency><groupId>io.seata</groupId><artifactId>seata-all</artifactId><version>1.5.2</version></dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity --><dependency><groupId>com.atguigu.springcloud</groupId><artifactId>cloud-api-common</artifactId><version>${project.version}</version></dependency><!--nacos--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--feign--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!--web-actuator--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!--mysql-druid--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><!--<version>5.1.37</version>--></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.10</version></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.0.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency></dependencies></project>

seata版本最好要吻合

5.2.3 YML

server:port: 2001spring:application:name: seata-order-servicecloud:nacos:discovery:server-addr: localhost:8848namespace: "6f25df50-1e22-4301-9587-d627b6158fc9"alibaba:seata:tx-service-group: fsp_tx_groupdatasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://localhost:3306/seata_orderusername: rootpassword: 123456feign:hystrix:enabled: falselogging:level:io:seata: infomybatis:mapperLocations: classpath:mapper/*.xmlseata:tx-service-group: fsp_tx_group  #这里每个服务都是对应不同的映射名,在配置中心可以看到registry:type: nacosnacos:server-addr: localhost:8848group: SEATA_GROUPnamespace: "6f25df50-1e22-4301-9587-d627b6158fc9"service:vgroup-mapping:#这里也要注意 key为映射名fsp_tx_group: default

5.2.4 修改seata路径下的/conf/application.yml

server:port: 7091spring:application:name: seata-serverlogging:config: classpath:logback-spring.xmlfile:path: ${user.home}/logs/seataextend:logstash-appender:destination: 127.0.0.1:4560kafka-appender:bootstrap-servers: 127.0.0.1:9092topic: logback_to_logstashconsole:user:username: seatapassword: seataseata:config:# support: nacos, consul, apollo, zk, etcd3type: nacosnacos:server-addr: http://127.0.0.1:8848namespace: 6f25df50-1e22-4301-9587-d627b6158fc9group: SEATA_GROUPusername: password: data-id: seataServer.propertiesregistry:# support: nacos, eureka, redis, zk, consul, etcd3, sofatype: nacosnacos:application: seata-serverserver-addr: http://127.0.0.1:8848group: SEATA_GROUPnamespace: 6f25df50-1e22-4301-9587-d627b6158fc9cluster: default   #这个还是有必要的,如果不配置的话,微服务一直报errorusername: password: 
#  store:# support: file 、 db 、 redis
#    mode: file
#  server:
#    service-port: 8091 #If not configured, the default is '${server.port} + 1000'security:secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017tokenValidityInMilliseconds: 1800000ignore:urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/api/v1/auth/login

5.2.6 遇到的问题和坑

问题1:

i.s.c.r.netty.NettyClientChannelManager:no available server to connect.

查看官方文档:https://github.com/seata/seata-samples/blob/master/doc/quick-integration-with-spring-cloud.md
看到在对 file.conf 的解释说明中提到:
在这里插入图片描述
在这里插入图片描述
此处一开始没配置,出现这个错误后加上

问题2:

i.s.c.r.netty.NettyClientChannelManager  : no available service found in cluster 'DEFAULT', please make sure registry config correct and keep your seata server running

在这里插入图片描述
在这里插入图片描述

5.2.7 domain

package com.atguigu.springcloud.domain;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** 简要描述** @Author: ASuLe* @Date: 2023/1/21 22:58* @Version: 1.0* @Description: 文件作用详细描述....*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult<T> {private Integer code;private String message;private T data;public CommonResult(Integer code, String message) {this(code, message, null);}
}
package com.atguigu.springcloud.domain;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.math.BigDecimal;/*** 简要描述** @Author: ASuLe* @Date: 2023/1/21 22:59* @Version: 1.0* @Description: 文件作用详细描述....*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Order {private Long id;private Long userId;private Long productId;private Integer count;private BigDecimal money;/*** 订单状态 0:创建中,1:已完结*/private Integer status;
}

5.2.8 Dao接口及实现

package com.atguigu.springcloud.dao;import com.atguigu.springcloud.domain.Order;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;/*** 简要描述** @Author: ASuLe* @Date: 2023/1/21 23:02* @Version: 1.0* @Description: 文件作用详细描述....*/
@Mapper
public interface OrderDao {//1.新建订单void create(Order order);//2.修改订单状态,从0改为1void update(@Param("userId") Long userId,@Param("status") Integer status);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.springcloud.dao.OrderDao"><resultMap id="BaseResultMap" type="com.atguigu.springcloud.domain.Order"><id column="user_id" property="userId" jdbcType="BIGINT"/><result column="product_id" property="productId" jdbcType="BIGINT"/><result column="count" property="count" jdbcType="INTEGER"/><result column="money" property="money" jdbcType="DECIMAL"/><result column="status" property="status" jdbcType="INTEGER"/></resultMap><insert id="create" parameterType="com.atguigu.springcloud.domain.Order" useGeneratedKeys="true"keyProperty="id">insert into t_order(user_id,product_id,count,money,status) values (#{userId},#{productId},#{count},#{money},0);</insert><update id="update">update t_order set status =1 where user_id =#{userId} and status=#{status};</update>
</mapper>

5.2.9 Service接口及实现

package com.atguigu.springcloud.service;import com.atguigu.springcloud.domain.Order;/*** 简要描述** @Author: ASuLe* @Date: 2023/1/21 23:12* @Version: 1.0* @Description: 文件作用详细描述....*/
public interface OrderService {void create(Order order);}
package com.atguigu.springcloud.service;import com.atguigu.springcloud.entities.CommonResult;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;import java.math.BigDecimal;/*** 简要描述** @Author: ASuLe* @Date: 2023/1/21 23:12* @Version: 1.0* @Description: 文件作用详细描述....*/
@FeignClient(value = "seata-account-service")
public interface AccountService {@PostMapping(value = "/account/decrease")CommonResult decrease(@RequestParam("userId") Long userId,@RequestParam("money") BigDecimal money);}
package com.atguigu.springcloud.service;import com.atguigu.springcloud.entities.CommonResult;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;/*** 简要描述** @Author: ASuLe* @Date: 2023/1/21 23:12* @Version: 1.0* @Description: 文件作用详细描述....*/
@FeignClient(value = "seata-storage-service")
public interface StorageService {@PostMapping(value = "/storage/decrease")CommonResult decrease(@RequestParam("productId") Long productId,@RequestParam("count") Integer count);
}
package com.atguigu.springcloud.service.impl;import com.atguigu.springcloud.dao.OrderDao;
import com.atguigu.springcloud.domain.Order;
import com.atguigu.springcloud.service.AccountService;
import com.atguigu.springcloud.service.OrderService;
import com.atguigu.springcloud.service.StorageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;import javax.annotation.Resource;/*** 简要描述** @Author: ASuLe* @Date: 2023/1/21 23:13* @Version: 1.0* @Description: 文件作用详细描述....*/
@Service
@Slf4j
public class OrderServiceImpl implements OrderService {@Resourceprivate OrderDao orderDao;@Resourceprivate StorageService storageService;@Resourceprivate AccountService accountService;@Overridepublic void create(Order order) {log.info("-------------->开始新建订单");//1.新建订单orderDao.create(order);log.info("-------------->订单微服务开始调用库存,做扣减Count");//2.扣减库存storageService.decrease(order.getProductId(), order.getCount());log.info("-------------->订单微服务开始调用库存,做扣减end");log.info("-------------->订单微服务开始调用账户,做扣减Money");//3.扣减账户accountService.decrease(order.getUserId(), order.getMoney());log.info("-------------->订单微服务开始调用账户,做扣减end");//4.修改订单状态,从0到1,1代表已经完成log.info("-------------->修改订单状态开始");//要把某个用户的状态从0改为1orderDao.update(order.getUserId(), 0);log.info("-------------->修改订单状态结束");log.info("-------------->下订单结束了,O(∩_∩)O~");}
}

5.2.10 Conrtoller

package com.atguigu.springcloud.controller;import com.atguigu.springcloud.domain.Order;
import com.atguigu.springcloud.entities.CommonResult;
import com.atguigu.springcloud.service.OrderService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;/*** 简要描述** @Author: ASuLe* @Date: 2023/1/21 23:27* @Version: 1.0* @Description: 文件作用详细描述....*/
@RestController
public class OrderController {@Resourceprivate OrderService orderService;@GetMapping("/order/create")public CommonResult create(Order order){orderService.create(order);return new CommonResult(200,"订单创建成功");}
}

5.2.10 Config配置

package com.atguigu.springcloud.config;import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;/*** 简要描述** @Author: ASuLe* @Date: 2023/1/24 10:09* @Version: 1.0* @Description: 文件作用详细描述....*/
@Configuration
@Data
public class DataSourceConfig {@Value("${spring.datasource.url}")private String url;@Value("${spring.datasource.username}")private String userName;@Value("${spring.datasource.password}")private String password;@Value("${spring.datasource.driver-class-name}")private String driveClassName;
}
package com.atguigu.springcloud.config;import com.zaxxer.hikari.HikariDataSource;
import io.seata.rm.datasource.DataSourceProxy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;import javax.sql.DataSource;/*** 简要描述** @Author: ASuLe* @Date: 2023/1/24 10:09* @Version: 1.0* @Description: 文件作用详细描述....*/
@Configuration
public class DataSourceProxyConfig {@Autowiredprivate DataSourceConfig dataSourceConfig;@Bean("dataSource")public DataSource druidDataSource() {HikariDataSource hikariDataSource = new HikariDataSource();hikariDataSource.setJdbcUrl(dataSourceConfig.getUrl());hikariDataSource.setUsername(dataSourceConfig.getUserName());hikariDataSource.setPassword(dataSourceConfig.getPassword());hikariDataSource.setDriverClassName(dataSourceConfig.getDriveClassName());return hikariDataSource;}@Bean@Primarypublic DataSourceProxy dataSourceProxy(DataSource dataSource) {return new DataSourceProxy(dataSource);}
}

5.2.11 主启动

package com.atguigu.springcloud;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;/*** 简要描述** @Author: ASuLe* @Date: ${DATE} ${TIME}* @Version: 1.0* @Description: 文件作用详细描述....*/
@EnableDiscoveryClient
@EnableFeignClients
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class SeataAccountApplication2003 {public static void main(String[] args) {SpringApplication.run(SeataAccountApplication2003.class, args);}
}

5.3 新建Storage-Module

5.3.1 新建seata-storage-service2002

5.3.2 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"><modelVersion>4.0.0</modelVersion><parent><groupId>com.atguigu.springcloud</groupId><artifactId>cloud2022</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>seata-storage-service2002</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><!--分布式事务 --><!--移除alibaba-seata自带的seata-spring-boot-starter,因为自带的版本太低 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId><exclusions><exclusion><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId></exclusion><exclusion><groupId>io.seata</groupId><artifactId>seata-all</artifactId></exclusion></exclusions></dependency><!--添加seata-spring-boot-starter依赖,版本需要与服务端版本相对应,此版本使用1.5.2 --><dependency><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId><version>1.5.2</version></dependency><dependency><groupId>io.seata</groupId><artifactId>seata-all</artifactId><version>1.5.2</version></dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity --><dependency><groupId>com.atguigu.springcloud</groupId><artifactId>cloud-api-common</artifactId><version>${project.version}</version></dependency><!--nacos--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--feign--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!--web-actuator--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!--mysql-druid--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><!--<version>5.1.37</version>--></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.10</version></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.0.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency></dependencies>
</project>

5.3.3 YML

server:port: 2002spring:application:name: seata-storage-servicecloud:nacos:discovery:server-addr: localhost:8848namespace: "6f25df50-1e22-4301-9587-d627b6158fc9"alibaba:seata:tx-service-group: fsp_tx_groupdatasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://localhost:3306/seata_storageusername: rootpassword: 123456feign:hystrix:enabled: falselogging:level:io:seata: infomybatis:mapperLocations: classpath:mapper/*.xmlseata:tx-service-group: fsp_tx_group  #这里每个服务都是对应不同的映射名,在配置中心可以看到registry:type: nacosnacos:server-addr: localhost:8848group: SEATA_GROUPnamespace: "6f25df50-1e22-4301-9587-d627b6158fc9"service:vgroup-mapping:#这里也要注意 key为映射名fsp_tx_group: default

5.3.4 修改seata路径下的/conf/application.yml

2001中已经配置过了

5.3.5 domain

package com.atguigu.springcloud.domain;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** 简要描述** @Author: ASuLe* @Date: 2023/1/21 22:58* @Version: 1.0* @Description: 文件作用详细描述....*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult<T> {private Integer code;private String message;private T data;public CommonResult(Integer code, String message) {this(code, message, null);}
}
package com.atguigu.springcloud.domain;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** 简要描述** @Author: ASuLe* @Date: 2023/1/23 14:31* @Version: 1.0* @Description: 文件作用详细描述....*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Storage {private Long id;/*** 产品id*/private Long productId;/*** 总库存*/private Integer total;/*** 已用库存*/private Integer used;/*** 剩余库存*/private Integer residue;
}

5.3.6 Dao接口及实现

package com.atguigu.springcloud.dao;import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;/*** 简要描述** @Author: ASuLe* @Date: 2023/1/23 14:32* @Version: 1.0* @Description: 文件作用详细描述....*/
@Mapper
public interface StorageDao {/*** 减库存* @param productId* @param count* @return*/void decrease(@Param("productId") Long productId, @Param("count") Integer count);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.springcloud.dao.StorageDao"><resultMap id="BaseResultMap" type="com.atguigu.springcloud.domain.Storage"><id column="id" property="id" jdbcType="BIGINT"></id><result column="product_id" property="productId" jdbcType="BIGINT"></result><result column="total" property="total" jdbcType="INTEGER"></result><result column="used" property="used" jdbcType="INTEGER"></result><result column="residue" property="residue" jdbcType="INTEGER"></result></resultMap><!--减库存--><update id="decrease">update t_storageset used   =used + #{count},residue=residue - #{count}where product_id = #{productId};</update></mapper>

5.3.7 Service接口及实现

package com.atguigu.springcloud.service;/*** 简要描述** @Author: ASuLe* @Date: 2023/1/23 14:35* @Version: 1.0* @Description: 文件作用详细描述....*/
public interface StorageService {void decrease(Long productId, Integer count);}
package com.atguigu.springcloud.service.impl;import com.atguigu.springcloud.dao.StorageDao;
import com.atguigu.springcloud.service.StorageService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;import javax.annotation.Resource;/*** 简要描述** @Author: ASuLe* @Date: 2023/1/23 14:36* @Version: 1.0* @Description: 文件作用详细描述....*/
@Service
public class StorageServiceImpl implements StorageService {private static final Logger LOGGER = LoggerFactory.getLogger(StorageServiceImpl.class);@Resourceprivate StorageDao storageDao;@Overridepublic void decrease(Long productId, Integer count) {LOGGER.info("------------------>storage-service中扣减库存开始");storageDao.decrease(productId, count);LOGGER.info("------------------>storage-service中扣减库存结束");}
}

5.3.8 Conrtoller

package com.atguigu.springcloud.controller;import com.atguigu.springcloud.domain.CommonResult;
import com.atguigu.springcloud.service.StorageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;/*** 简要描述** @Author: ASuLe* @Date: 2023/1/23 14:39* @Version: 1.0* @Description: 文件作用详细描述....*/
@RestController
public class StorageController {@Autowiredprivate StorageService storageService;/*** 减库存** @param productId* @param count* @return*/@PostMapping(value = "/storage/decrease")public CommonResult decrease(@RequestParam("productId") Long productId, @RequestParam("count") Integer count) {storageService.decrease(productId, count);return new CommonResult(200, "扣减库存成功");}
}

5.3.9 Config配置

package com.atguigu.springcloud.config;import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;/*** 简要描述** @Author: ASuLe* @Date: 2023/1/24 10:09* @Version: 1.0* @Description: 文件作用详细描述....*/
@Configuration
@Data
public class DataSourceConfig {@Value("${spring.datasource.url}")private String url;@Value("${spring.datasource.username}")private String userName;@Value("${spring.datasource.password}")private String password;@Value("${spring.datasource.driver-class-name}")private String driveClassName;
}
package com.atguigu.springcloud.config;import com.zaxxer.hikari.HikariDataSource;
import io.seata.rm.datasource.DataSourceProxy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;import javax.sql.DataSource;/*** 简要描述** @Author: ASuLe* @Date: 2023/1/24 10:09* @Version: 1.0* @Description: 文件作用详细描述....*/
@Configuration
public class DataSourceProxyConfig {@Autowiredprivate DataSourceConfig dataSourceConfig;@Bean("dataSource")public DataSource druidDataSource() {HikariDataSource hikariDataSource = new HikariDataSource();hikariDataSource.setJdbcUrl(dataSourceConfig.getUrl());hikariDataSource.setUsername(dataSourceConfig.getUserName());hikariDataSource.setPassword(dataSourceConfig.getPassword());hikariDataSource.setDriverClassName(dataSourceConfig.getDriveClassName());return hikariDataSource;}@Bean@Primarypublic DataSourceProxy dataSourceProxy(DataSource dataSource) {return new DataSourceProxy(dataSource);}
}

5.3.10 主启动

package com.atguigu.springcloud;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;/*** 简要描述** @Author: ASuLe* @Date: ${DATE} ${TIME}* @Version: 1.0* @Description: 文件作用详细描述....*/
@EnableDiscoveryClient
@EnableFeignClients
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class SeataStorageServiceApplication2002 {public static void main(String[] args) {SpringApplication.run(SeataStorageServiceApplication2002.class, args);}
}

5.4 新建Account-Module

5.4.1 新建seata-account-service2003

5.4.2 POM

5.4.3 YML

5.4.4 修改seata路径下的/conf/application.yml

5.4.5 domain

5.4.6 Dao接口及实现

5.4.7 Service接口及实现

5.4.8 Conrtoller

5.4.9 Config配置

package com.atguigu.springcloud.config;import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;/*** 简要描述** @Author: ASuLe* @Date: 2023/1/24 10:09* @Version: 1.0* @Description: 文件作用详细描述....*/
@Configuration
@Data
public class DataSourceConfig {@Value("${spring.datasource.url}")private String url;@Value("${spring.datasource.username}")private String userName;@Value("${spring.datasource.password}")private String password;@Value("${spring.datasource.driver-class-name}")private String driveClassName;
}
package com.atguigu.springcloud.config;import com.zaxxer.hikari.HikariDataSource;
import io.seata.rm.datasource.DataSourceProxy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;import javax.sql.DataSource;/*** 简要描述** @Author: ASuLe* @Date: 2023/1/24 10:09* @Version: 1.0* @Description: 文件作用详细描述....*/
@Configuration
public class DataSourceProxyConfig {@Autowiredprivate DataSourceConfig dataSourceConfig;@Bean("dataSource")public DataSource druidDataSource() {HikariDataSource hikariDataSource = new HikariDataSource();hikariDataSource.setJdbcUrl(dataSourceConfig.getUrl());hikariDataSource.setUsername(dataSourceConfig.getUserName());hikariDataSource.setPassword(dataSourceConfig.getPassword());hikariDataSource.setDriverClassName(dataSourceConfig.getDriveClassName());return hikariDataSource;}@Bean@Primarypublic DataSourceProxy dataSourceProxy(DataSource dataSource) {return new DataSourceProxy(dataSource);}
}

5.4.10 主启动

package com.atguigu.springcloud;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;/*** 简要描述** @Author: ASuLe* @Date: ${DATE} ${TIME}* @Version: 1.0* @Description: 文件作用详细描述....*/
@EnableDiscoveryClient
@EnableFeignClients
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class SeataAccountApplication2003 {public static void main(String[] args) {SpringApplication.run(SeataAccountApplication2003.class, args);}
}

6.测试

6.1数据库初始情况

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6.2 正常下单

测试地址: http://localhost:2001/order/create?userId=1&productId=1&count=10&money=100
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6.3 超时异常,没加@GlobalTransactional

在2003的AccountS中模拟超时异常
在这里插入图片描述

在此处睡20秒,OpenFeign的调用默认时间是1秒钟,现在睡20秒肯定报超时异常

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
故障情况:

  • 当库存和账户金额扣减后,订单状态没有设置为已完成,没有从0改为1
  • 而且由于feign重试机制,账户余额还有可能被多次扣减

6.4 超时异常,添加@GlobalTransactional

业务入口2001的OrderServiceImpl上添加@GlobalTransactional
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.补充

7.1 Seata

2019年1月蚂蚁金服和阿里巴巴共同开源的分布式事务解决方案

Simple Extensible Autonomous Transaction Architecture,简单可扩展自治事务框架

2020年起始,参加工作后用1.0以后的版本

7.2 再看TC/TM/RM三大组件

在这里插入图片描述
在这里插入图片描述
分布式事务的执行流程:

  1. TM开启分布式事务(TM向TC注册全局事务记录)
  2. 按业务场景,编排数据库、服务等事务内资源(RM向TC汇报资源状态)
  3. TM结束分布式事务,事务一阶段结束(TM通知TC提交/回滚分布式事务)
  4. TC汇总事务信息,决定分布式事务是提交还是回滚
  5. TC通知所有RM提交/回滚资源,事务二阶段结束。

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

7.3.1 是什么

在这里插入图片描述

7.3.2 一阶段加载

在一阶段,Seata会拦截"业务SQL"

  1. 解析SQL语义,找到"业务SQL"要更新的业务数据,在业务数据被更新前,将其保存成"before image"
  2. 执行"业务SQL"更新业务数据
  3. 在业务数据更新之后,将其保存成"after image",最后生产行锁

以上操作全部在一个数据库事务内完成,这样保证了一阶段操作的原子性
在这里插入图片描述

7.3.3 正常情况二阶段提交

二阶段如果顺利提交的话,因为"业务SQL"在一阶段已经提交至数据库,所以Seata框架只需将一阶段保存的快照数据和行锁删掉,完成数据清理即可。
在这里插入图片描述

7.3.4 异常情况二阶段回滚

二阶段如果是回滚的话,Seata就需要回滚一阶段已经执行的"业务SQL",还原业务数据。

回滚方式便是使用"before image"还原业务数据;但在还原前首先要校验脏写,对比"数据库当前业务数据"和"after image",如果两份数据完全一致就说明没有脏写,可以还原业务数据,如果不一致就说明有脏写,出现脏写就需要转人工处理。
在这里插入图片描述

7.4 debug

修改2003的AccountServiceImpl
在这里插入图片描述
在这里插入图片描述

debug运行,测试地址,观察seata库
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在undo_log表的rollback_info都有记录
在这里插入图片描述

如果成功了那就没问题,如果失败了就反补,就是把修改的数据根据before image(记录了修改之前的值和修改之后的值)回退到原始的数据状态,还原前首先要校验脏写,如果高并发条件下,28改成了32,别人已经在我之前动过这个数据了,我就改不回去了,类似于乐观锁
在这里插入图片描述
这几张表都锁了

7.5 补充

在这里插入图片描述


相关文章:

  • MODBUS总线的学习笔记
  • OSG三维渲染引擎编程学习之二十七:“第三章:OSG场景组织” 之 “3.9 AutoTransform自动对齐节点”
  • 最实用的 Docker 知识(一)
  • Leetcode:78. 子集、90. 子集 II(C++)
  • 1月23日Linux c编程之Makefile
  • UPS BP650CH实现nas自动关机
  • MySQL —— 库操作
  • ❤️如何实现所谓的“关键字传参”--理论+易懂版⭐
  • 【JavaEE】认识线程Thread类及常用方法线程状态
  • Shell语法
  • MP-2平面烟雾气体传感器介绍
  • springboot中restful风格请求的使用
  • 【19】C语言 | 三子棋
  • 【每日一题Day97】LC1828统计一个圆中点的数目 | 模拟
  • 议论文书写总结
  • Day869.索引(下) -MySQL实战
  • 离线召回与排序介绍
  • 【Ajax】防抖和节流
  • CMAKE
  • 【面试克星】【公式少代码少话多】Vins-Mono预积分相关知识点总结与概述
  • C语言基础知识(36)
  • Python实现一个简易的CLI翻译程序
  • SQL学习
  • 【计组笔记01】计算机组成原理之冯诺依曼体系结构、计算机编码、定点数的表示、原码和补码的乘除法
  • 人世正道沧桑,她亦奋力向前 --读《李清照传》有感
  • Android 深入系统完全讲解(37)
  • 【QT5.9】与MFC对比学习笔记-感悟篇2【2023.01.23】
  • ARP渗透与攻防(五)之Ettercap劫持用户流量
  • C++初阶--继承
  • 学习率衰减、局部最优、Batch归一化、Softmax回归
  • 树状数组(代码模板和原理详解)
  • 我的第一次真实对国外某购物平台web漏洞挖掘
  • Intellij IDEA 丢失 Project Structure 问题
  • 分享139个ASP源码,总有一款适合您
  • Java | 解决并发修改异常问题【CurrentModificationException】
  • Mybatis遇到的脑残问题
  • 为了方便项目打包,我用Node写了个git-tag工具
  • RK3399平台开发系列讲解(内存篇)访问虚拟内存的物理内存过程
  • Essential C++第五章习题
  • JDK8 新特性之并行的Stream流
  • Cesium:Indexed 3D Scene Layers (I3S)加载
  • 【代码阅读】MSC-VO
  • Python基础学习六
  • 使用 AJAX+JSON 实现用户查询/添加功能
  • 在linux下安装docker
  • 【Hadoop】HDFS+Shell实践(定时上传数据至HDFS)
  • 《Rust权威指南》读书笔记9 - 泛型、特性、生命周期
  • 文本情感分类TextCNN原理+IMDB数据集实战
  • 【蓝桥杯】历届真题 作物杂交(省赛)Java
  • Tkinter的Listbox控件
  • 进阶C语言 第二章-------《进阶指针》 (指针数组、数组指针、函数指针、回调指针)知识点+基本练习题+深入细节+通俗易懂+完整思维导图+建议收藏
  • 梯度之上:Hessian 矩阵
  • Ubiquiti MAC Address Changer 3.0 Crack
  • 机器学习(五):机器学习算法分类
  • 路由处理及功能(实现了权限控制vue admin)
  • 【JavaSE专栏5】Java 基本数据类型和取值范围
  • 英语学习打卡day4
  • 【数据库概论】3.1 SQL简述、数据定义和索引
  • 【C语言进阶】一文带你学会C语言文件操作
  • 欧几里得与扩展欧几里得算法(含推导过程及代码)
  • 【My Electronic Notes系列——晶闸管】
  • 安装配置Ecplise插件PyDev 8.3.0
  • LeetCode刷题记录---贪心算法
  • 蓝桥杯-刷题-补基础
  • 多线程不安全函数的理解
  • 插入排序算法的实现和优化~
  • 协调中心性能大对比:zookeeper是如何解决负载均衡问题的
  • Email Signature Manager 9.3 Crack
  • CSS边框、边距、轮廓(边框宽度/颜色/各边/简写属性/圆角边框/内外边距/高度宽度/框模型/轮廓宽度/颜色/属性/偏移)——万字长文|一文搞懂
  • 2022——>2023
  • 【手写 Vue2.x 源码】第四十二篇 - 组件部分 - 组件挂载流程简述
  • 数据结构 最短路径课设(源码+实验报告+视频讲解)(用了自取)
  • 高等数学(第七版)同济大学 习题12-6 个人解答
  • Nacos集群搭建
  • JVM快速入门学习笔记(三)
  • 作为项目经理,如何做好项目进度管理
  • Linux进程信号
  • 我的1周年创作纪念日
  • 量子力学奇妙之旅-微扰论和变分法
  • CS61A 2022 fall HW 01: Functions, Control
  • MySQL主从复制、读写分离
  • NR PUSCH(七) 相干传输
  • 【Java|golang】1828. 统计一个圆中点的数目
  • Nginx与LUA(7)
  • 设计模式 - 六大设计原则之LoD(迪米特法则原则)
  • C++程序设计——动态内存管理
  • Leetcode:93. 复原 IP 地址(C++)
  • 《TPM原理及应用指南》学习 —— TPM实体4
  • 树,堆,二叉树的认识
  • OSG三维渲染引擎编程学习之二十五:“第三章:OSG场景组织” 之 “3.7 PositionAttitudeTransform位置姿态变换节点”
  • 几种觉排序优劣
  • 【C++】右值引用和移动语义 | 新的类功能 | 可变参数模板
  • 园区网典型组网架构及案例实践
  • 【学习Arduino单片机AD传感器采样的十大滤波算法】
  • PAT 1074 宇宙无敌加法器(C++解法)
  • Kubernetes:基于命令行终端UI的管理工具 K9s
  • 【JavaSE】一文看懂构造器/构造方法(Cunstructor)
  • 排序算法: 数据的离散化(排序+去重 C++例题实现)
  • 【每日一道智力题】之海盗分金币(上)
  • TypeScript
  • C++第七讲——Demon和Angela的魔法之旅
  • 美团出品 | YOLOv6 v3.0 is Coming(超越YOLOv7、v8)
  • CSS样式基础内容2
  • 【C++】类和对象(上)---什么是类?
  • 【头歌】单链表的基本操作
  • ConcurrentHashMap的死循环问题
  • C++6:STL-模拟实现string
  • 一文吃透python多线程(全面总结)
  • 计算机基础——无处不网络(2)
  • Docker安装教程(看这篇就够了)
  • 高性能 Java 框架。Solon v1.12.3 发布(春节前兮的最后更)
  • 内存函数及其模拟实现
  • Spring介绍
  • scala函数柯里化
  • C++基础回顾
  • 深度学习数据自动标注器开源 目标检测和图像分类(高精度高效率)
  • Redis脑裂为何会导致数据丢失?
  • Spring控制反转(IoC)和依赖注入(DI)
  • 客快物流大数据项目(一百零八):Spring Cloud 技术栈
  • CUDA编程笔记(5)
  • 【SpringCloud】Nacos注册中心、配置中心用法与原理(下)
  • Python 超强命令行解析工具 argparse !
  • 【C++】lambda 表达式 | 包装器
  • JQUERY案例
  • 第九层(1):初识STL
  • 【蓝桥云课】最大公约数与最小公倍数
  • Redis常用的数据类型
  • 抖音小黄车挂淘宝店相关问题记录
  • 【C语言进阶】指针进阶(干货)
  • 棋盘放麦子-蓝桥杯
  • 【Hadoop】HDFS高可用与高扩展原理分析(HA架构与Federation机制)
  • 23种设计模式(二十二)——访问者模式【行为变化】
  • 3.1 卷积神经网络的应用领域|卷积的作用|卷积特征值的计算方法|得到特征图表示|步长与卷积核大小对结果的影响|边缘填充方法
  • 安卓S开机动画流程
  • react源码:目录结构、调试源码
  • 车辆占用应急车道识别抓拍系统 opencv
  • 2022年“网络安全”赛项黑龙江省赛选拔赛 任务书
  • Webpack5 教程 (7) --- 减少代码
  • Elasticsearch7.8.0版本入门——JavaAPI操作(环境准备)
  • 常见递归模式
  • 偷偷理解Java和Scala中==和equals()的区别
  • 基于双层优化的微电网系统规划设计方法(Matlab代码实现)
  • STL - 常用算法
  • 基于Springboot+Vue+Sercurity实现的大学生健康管理平台
  • Linux内核驱动初探(二) TI声卡
  • 有关Java多线程的几个概念
  • JavaEE 突击 5 - Spring 更简单的读取和存储对象(2)
  • 约数个数及约数之和知识点(含公式)
  • 50个常用的 Numpy 函数详解
  • JavaEE5-Spring更简单的读取和存储对象
  • 过完2022,依然记得仰望星空
  • MyBatis 连接数据库与增删改查
  • Java标准输入输出流(in/out)
  • 【Python百日进阶-Web开发-Linux】Day236 - Win11安装Windows Subsystem for Android(WSA)
  • java8新特性
  • cmake 目录
  • C++进阶 哈希表封装unordered_map和unordered_set
  • Spring事务、事务隔离级别、事务传播机制
  • 【13】C语言 | “go_to“语句
  • Vue3悬浮返回主页按钮设计与实现
  • XILINX FPGA OV5640 摄像头驱动(一)
  • 合宙ESP32C3上手使用
  • 英语学习打卡day3
  • 2.4总线操作和定时
  • 8.Java循环高级综合练习-无限循环和跳转控制语句,逢七过,平方根,判断是否为质数,猜数字小游戏
  • 基于networkx聚类技术—复杂网络社团检测(附完整版代码)
  • avb校验相关与块校验原理
  • SpringBoot 统一功能处理
  • 基于PythonOpenCv的视频图像处理
  • 力扣sql简单篇练习(五)
  • Java---微服务---SpringCloud(2)
  • 【手写 Vue2.x 源码】第四十一篇 - 组件部分 - 生成组件的真实节点
  • 02 |「数据结构、逻辑结构、物理结构」基本概念简析
  • 06_平台总线匹配规则,自己搭建总线xbus
  • 什么是数据库连接池?Druid(德鲁伊)连接池的使用详细解读
  • 自己动手写一个操作系统——MBR(1)
  • Redis在秒杀场景的作用
  • await 返回了什么
  • pytorch零基础实现手写数学符号识别项目(三)——模型训练与预测
  • eBPF 入门开发实践指南五:在 eBPF 中使用 uprobe 捕获 bash 的 readline 函数调用
  • windows权限维持方法详解
  • 【LeetCode】二叉树的序列化与反序列化 [H](二叉树)
  • 【JavaSE专栏4】关键字、标识符和命名规范
  • 使用小程序+网页简易实现多客户端实时弹幕
  • 【JavaScript】多态(Symbol),迭代器接口,getter/setter
  • Java/JavaScript有哪些图形图像处理的框架?
  • Unity HurricaneVR 插件中的 VRIK 设置
  • Maplab 2.0发布:多传感器融合的SLAM框架,支持多机器人、语义回环检测功能
  • 汇报写作学习总结
  • Java中的hashCode,真的很容易弄懂
  • 域环境搭建
  • 单片机扫盲
  • C++:类的构造函数与析构函数
  • Canal实时同步发送JSON数据示例代码
  • 《TPM原理及应用指南》学习 —— TPM实体3
  • 面试官问我有没有分布式系统开发经验,我一脸懵圈…
  • 七、python-PySpark篇(黑马程序猿-python学习记录)
  • redis 数据库简介
  • 多线程(5)
  • mysql锁
  • 你对CSS权重真的足够了解吗?
  • E2PROM 蓝桥杯 stm32 AT24C02读写函数
  • 【SpringBoot】SpringBoot三层开发
  • Redis数据类型简介
  • 深度学习TensorFlow—GPU2.4.0版环境配置,一文简单易懂详细大全,CUDA11.0、cuDNN8.0
  • YOLOv5/v7 引入 YOLOv8 的 C2f 模块
  • 1月24日,30秒知全网,精选7个热点
  • MySQL(五):事务简介、事务的特性、事务的概念及状态、支持事务的引擎
  • 顺序表的具体使用方法.数据解构(二)
  • UE INI文件操作 INI File Operation [ Read / Write ] 插件说明
  • 【程序环境和程序预处理】万字详文,忘记了,看这篇就对了
  • 从零开始的python基础教程
  • STL分析(九 适配器)
  • MySQL间隙锁详细分析
  • 使用C++实现学委作业管理系统
  • 【IDEA】自动部署SpringBoot Jar包到远程服务器并通过脚本启动jar
  • 【My Electronic Notes系列——三极管】
  • 【操作系统】—— 如何安装双系统与多系统(带你快速了解)
  • OSG三维渲染引擎编程学习之八:“第一章:OSG介绍” 之 “1.8 基于QT的第三方库编译”
  • 三、利用迁移学习进行模型微调(Datawhale组队学习)
  • Kubernetes:分享一个很简洁的 k8s 管理工具 Skooner
  • <C++>哈希
  • Day09 - 子类父类多继承多层继承多态
  • Python---字典相关知识
  • fpga实操训练(一个典型的fpga系统)
  • 【剧前爆米花--爪哇岛寻宝】Java中有关异常类的详细讲解
  • Centos7 Docker安装APISIX
  • 06-jquery函数
  • C语言中不定参数 ... 的语法、函数封装
  • Cadence PCB仿真使用Allegro PCB SI生成振铃ringing仿真报告及报告导读图文教程
  • Kubernetes:通过 kubectl 插件 kubectl-tree 查看API对象层级关系
  • 博客系统项目的自动化测试
  • 深入剖析JVM垃圾收集器
  • 【并发编程十二】c++20线程同步——信号量(semaphore)
  • 深度估计算法原理与论文解读
  • 【Android】手机安装Termux运行nodejs学习Javascript编程入门
  • JAVA练习29
  • MySQL —— 数据库基础
  • 【HBase入门】2. 集群搭建
  • 【蓝桥杯】简单数论2——快速幂矩阵快速幂
  • 十二、网络基础2
  • 【数据结构】二叉搜索树的实现
  • 【文本分类实战练习】使用多个经典神经网络模型(词嵌入 词向量 LSTM CNN ),含问题记录及解决。
  • JDBC快速入门,如何使用JDBC操作数据库?
  • 20230123英语学习
  • 7个流行的强化学习算法及代码实现
  • Spring笔记上(基于XML配置)
  • 【目标检测论文解读复现NO.25】基于改进Yolov5的地铁隧道附属设施与衬砌表观病害检测方法
  • Go Data race and Vector clock
  • 前后端联调经验总结
  • Java多线程(二)—— ReentrantLock 源码分析
  • Springcloud 笔记
  • C++虚继承,虚基表 ,菱形继承以及解决方法
  • 我的硕士前半生
  • 【设计模式】我终于读懂了外观模式。。。
  • 【苹果家庭群发推】软件keychain中刚打开的证书下载的证书文件要决不会报错 UNTimeIntervalNotificationTrigge
  • 《Rust权威指南》读书笔记8 - Error handling 错误处理
  • CSS 特效之心形-彩虹-加载动画
  • 使用 Grafana 请求API接口
  • cmake 04 使用 python 管理 cmake 工程
  • POJ 1845 Sumdiv题解(C++ 整数惟一分解定理+分治法求等比数列之和+快速幂)
  • macm1使用Docker制作jar镜像并连接宿主机mysql
  • Vue TypeScript 使用eval函数的坑
  • CSDN原创图片链接失效分析
  • postgresql源码学习(52)—— vacuum①-准备工作与主要流程
  • 学习记录668@项目管理之项目沟通管理和干系人管理
  • Linux条件判断(全)
  • 【手写 Vue2.x 源码】第四十篇 - 组件部分 - 组件的生命周期
  • 01_kobject和ktype创建设备文件和设备目录
  • 大数据之HBase集群搭建
  • 我的创作纪念日——“永远相信美好的事情即将发生”
  • 期货交易原理(期货交易原理与实务)
  • C语言基础知识总结大全(五)
  • Linux——innode
  • 一本通-1033:计算线段长度
  • Python数模笔记-模拟退火算法(5)求解旅行商问题的联合算子模拟退火算法
  • 【青训营】Go语言的基本语法
  • HashMap1.7中的线程安全问题
  • 数学表达式的处理
  • casbin权限和配置文件的理解
  • 详解1247:河中跳房子(二分经典例题)
  • Yolo系列理论
  • 尚硅谷前端ES6-ES11
  • 08 |「双指针」算法分析
  • ROS2机器人编程简述humble-第三章-PERCEPTION AND ACTUATION MODELS .1
  • 高等数学【合集】
  • sbt编程语言scala的构建工具配置及项目构建(附带网盘下载)
  • 【蓝桥杯】历届真题 质数行者(决赛)Java
  • Java多线程(二)——ReentrantLock源码解析(补充2——可打断的锁)
  • 如何与他人交流
  • JavaScript 入门基础 - 对象(五)
  • 网关超详解
  • Multiple Dimension Input 处理多维特征的输入
  • React源码之render过程中发生了什么?
  • java spring IOC xml 方式 内部Bean注入
  • JavaScript 输出
  • 《啊哈算法第四章之bfs》(17张图解)
  • ArcGIS Pro脚本工具(17)——生成多分式标注
  • 【手写 Vue2.x 源码】第三十九篇 - 组件部分 - 创建组件虚拟节点
  • 【MySQL进阶】MySQL事务详解
  • Maplab:一个用于视觉惯性建图和定位研究的开源框架
  • 代码随想录--字符串习题总结
  • 【pytorch】.mul .add_ 和直接 + * 有什么区别
  • 2022年度总结:反思与回顾
  • 动态规划(基础)
  • 分享129个ASP源码,总有一款适合您
  • 第55章 SQL EXISTS 运算符教程
  • 【模拟CMOS集成电路】电路失调与CMRR—— 随机失调与系统失调分析(1)
  • 《MLB美职棒大联盟》:赛扬奖·棒球1号位
  • 文件操作和IO
  • java入门作业-DAO,读取sql数据库
  • Python基础学习 -- 文件操作
  • Python 匿名函数
  • STM32编写OLED显示屏驱动
  • 春节假期后,如何快速让员工恢复上班的元气和状态?
  • 【Unity Shader 赛博小人01】UV准备 SD制作特效贴图
  • Git使用Merge和Rebase区别及心得技巧
  • 20230123使AIO-3568J开发板在Android12下永不休眠
  • 【回望2022,走向2023】一个双非二本非科班的学生的旅途
  • 【经典算法】双指针(尺取法):爱,是双向奔赴,还是你追我赶?
  • Redis内部的阻塞式操作以及应对方法
  • 2023年大年初一 —— 牛客网刷题经验分享~
  • 一、pyhon准备工作篇(黑马程序猿-python学习记录)
  • AcWing第87场周赛题解
  • 【每日一道智力题】之蚂蚁走树脂和绳子秒表
  • 【Vue】我的尚品汇项目笔记---20230109~20230120
  • eBPF 入门开发实践指南一:介绍 eBPF 的基本概念、常见的开发工具
  • 数据结构 最短路径课设(源码+实验报告+视频讲解)(不要钱、用了自取)
  • autojs模仿QQ长按弹窗菜单(二)
  • python能做的100件事03-python爬虫
  • 【求职】济南地区-运维工程师
  • SpringBoot+Vue项目月度员工绩效考核管理系统
  • 实现升序降序排列问题
  • C++普通类,派生类,虚基类的成员构造顺序以及构造函数调用顺序详解
  • 每日算法4 —— UVa10474 大理石在哪里? Where is the Marble?
  • 【进击的算法】基础算法——动态规划
  • logstash + logback实现分布式日志采集
  • 在java中操作redis
  • 线程常用方法及常见状态
  • JDK8 新特性之Stream流方法详解
  • 设计模式之原型模式
  • 【C++】从0到1入门C++编程学习笔记 - 核心编程篇:类和对象(下)
  • 7.Java判断和循环+面试相关力扣算法题详解
  • 【Kotlin】泛型 ① ( 泛型类 | 泛型参数 | 泛型函数 | 多泛型参数 | 泛型类型约束 )
  • Java 23种设计模式(2.创建者模式-工厂设计模式)
  • Java基础进阶
  • 【附代码】python绘图集锦-关系Correlation图
  • 【蓝桥杯】历届真题 蓝肽子序列(决赛) Java
  • 【大数据hive】hive ddl语法使用详解
  • linux系统中使用QT实现APP开发的基本方法
  • Linux基本功系列之rename命令实战
  • 2023-1-22 刷题情况
  • Java面试题,Spring Bean的注册与依赖注入
  • 什么是数字经济
  • Java 集合之Stream流
  • Tkinter的Entry与Text
  • 二维费用背包问题
  • while循环——求100以内偶数和
  • 04 |「链表」简析
  • RESTful开发风格 与 SpringMVC跨域访问
  • eBPF 入门开发实践指南二:在 eBPF 中使用 kprobe 监测捕获 unlink 系统调用
  • 【ARM体系结构】之相关概念与公司简介
  • 超级完整的 Git 下载、安装与配置
  • Tkinter的Menu与Messagebox
  • (考研湖科大教书匠计算机网络)第二章物理层-第一、二节:物理层基本概念和传输媒体
  • ARP渗透与攻防(一)之ARP原理
  • English Learning - L1-13 主动脉修饰 (上) 2023.1.16 周一
  • 从零实现一个组件库(一)项目环境搭建
  • acwing基础课——快速幂
  • 双指针思想,c语言
  • 【HTML | CSS】春节将至,为网页挂上精美的灯笼吧(附源码)程序员的浪漫
  • 第三章 AOP
  • 【leetcode】学了栈和队列却觉得无用武之地?试试这几道题目吧!
  • CMMI之工程类
  • 【算法题】1604. 警告一小时内使用相同员工卡大于等于三次的人
  • 【Leetcode面试常见题目题解】8. 合并两个有序链表
  • linux系统中利用QT实现视频监控的基本方法
  • Python数据可视化之条形图和热力图
  • 浅析Spring的五大类注解和方法注解
  • 【蓝桥杯】历届真题 蓝肽子序列 Java
  • Kotlin 中 infix 函数的应用:构建清晰易读的语法
  • 机器学习(四):机器学习工作流程
  • 零基础学MySQL(三)-- 对表中数据的增删改【新年快乐】
  • Nacos注册中心
  • PAT 1058 选择题(C++实现)
  • 【手写 Vue2.x 源码】第三十七篇 - 组件部分 - 组件的合并
  • 【Java】比较器 Comparator Comparable
  • HTTPS 是这样握手的
  • 【每日一题Day96】LC2303计算应缴税款总额 | 模拟
  • 看我使用Python秒变高级程序员
  • 目录 行盒的盒模型 显著特点 行块盒 空白折叠 可替换元素 和 非可替换元素 分页例子 display:inline-block object-fit
  • 函数式编程之stream开发实战
  • 基于android手机选课系统的设计与实现
  • 【Android笔记68】Android之相机控制类Camera相关操作的API介绍(Camera已过期不推荐)
  • LeetCode_单周赛_329
  • 第十届蓝桥杯省赛 C++ A/B组 - 完全二叉树的权值
  • <Python的文件>——《Python》
  • 扩散模型 Diffusion Models 入门到实践 | 论文、学习资源、课程整理
  • Linux常用命令——strace命令
  • 字节青训前端笔记 | Web安全
  • Java | 浅谈多态中的向上转型与向下转型
  • 【MySQL】第九部分 MySQL信息函数
  • 生物化学 电阻抗成像OpenEIT,Dbar算法,数据集等(暂记)
  • python基础——列表推导式
  • 自定义Filter后,我的业务代码怎么被执行了多次?
  • 5-2中央处理器-指令周期的数据流
  • day25-类加载器反射
  • 3.5 拉普拉斯定理
  • 【操作系统】—— Windows卸载与清除工具“ Geek 与 CCleaner ” (带你快速了解)
  • Socket通信
  • 860.柠檬水找零 406.根据身高重建队列 452. 用最少数量的箭引爆气球 435. 无重叠区间
  • Java EE之线程编(进阶版)
  • 零入门容器云实战之文章目录列表
  • expect实现无交互操作
  • Linux进程学习【一】
  • 跨平台freebasic集锦(4)-基本语法(3)-dim(3)
  • 2022年,经历了两段实习后,我学会了……
  • JVM面试一
  • Sprig框架集成(SSM框架) | Sping+SpringMVC+Mybatis
  • 【计算机网络】HTTP/HTTPS
  • 【MySQL】第八部分 加密和解密函数
  • 线性代数[向量]
  • PHP XML DOM
  • Couplet | 用Python写一副对联送给诸位科研汪!~
  • 线段树学习
  • 分享130个ASP源码,总有一款适合您
  • 高等数学(第七版)同济大学 习题12-3 个人解答
  • linux shell脚本学习
  • 当你编码时
  • 汇编【王爽】实验8、9
  • 第四章必备前端基础知识-第二节2:CSS属性
  • P2615 [NOIP2015 提高组] 神奇的幻方
  • Allegro如何统计包含过孔长度的网络长度操作指导
  • Java-线程基础
  • 【C++】从0到1入门C++编程学习笔记 - 实战篇:职工管理系统
  • 目标检测论文解读复现【NO.24】改进 YOLOv5s 的轨道障碍物检测模型轻量化研究
  • 将字符串代码编译为字节代码对象 compile()
  • Java的基本语法格式
  • 进程概念——Linux
  • Java面试题,JVM相关问题
  • Windows 服务器刷题(2)(带答案)
  • liunx centos9安装nodejs并搭建vue 图文详解手把手教程
  • Android 国际化
  • 【基础】BMP格式
  • 使用账号激活MATLAB软件
  • 【ArcGIS微课1000例】0059:三种底图影像调色技巧案例教程
  • Java基础练习题(四)
  • 从0开始深入学习Elasticsearch
  • JQUERY总结(四)
  • Week 12
  • 狂神。JVM入门学习笔记。
  • HDFS高可用单NameNode从standby恢复为active(二)
  • day23-网络编程01
  • Solid Edge 放样使用引导曲线
  • 基于双层共识控制的直流微电网优化调度(Matlab代码实现)
  • 使用Py6S计算瑞利反射率教程
  • 走进 HTML
  • 我用笨办法啃下了一个开源项目的源码!
  • 第四十四章 动态规划——背包问题模型(一)
  • 3.7 克拉默法则
  • Ubuntu显示优化 动画
  • 动态规划完全背包 fullbackpack
  • 第十三届蓝桥杯省赛 JAVA A组 - 蜂巢
  • C语言-qsort函数基本使用
  • 创建者模式-建造者模式
  • 卷积神经网络进阶--基础知识
  • 十六进制转八进制+超大数据处理(蓝桥杯基础练习C/C++)
  • 《深入浅出计算机组成原理》学习笔记 Day7
  • Windows SDK编程 初学笔记
  • vue学习笔记(更新中)
  • 2023年springboot面试题集合
  • Python烟花秀
  • 左值和右值的概念
  • pytorch 神经网络笔记-RNN和LSTM
  • KK集团再冲刺港交所上市:期内被罚款30万元,曾存在“二清”问题
  • 【JavaSE】保姆级教程|1万字+10张图学会类与对象--建议收藏
  • k8s之挂载NFS到POD中
  • Kettle(4):excel数据抽取到mysql
  • 【学习笔记】[AGC030F] Permutation and Minimum
  • 07 | 应届生身份为什么重要?只有一次
  • RSD高分卫星数据处理能力提升——日正射处理数千景高分数据集
  • python练习|面向对象--其他
  • 【Java|golang】2287. 重排字符形成目标字符串
  • 3.开发社区首页
  • 【React】组件的创建与事件绑定
  • iToF,dToF,CMOS的Binning Mode
  • 【自然语言处理】Gensim中的Word2Vec
  • 文件权限控制篇
  • 虚幻引擎中CityEngine导入资产的自动化替换
  • 过滤器Filter总结
  • 关于精简(函数化)因为输入数据多条而导致的冗杂代码的总结
  • Java基础之《netty(30)—RPC调用流程分析》
  • 3.3 Dodgson算法
  • LwIP系列--内存管理(堆内存)详解
  • Kettle(3):快速入门
  • 【机器学习】特征选择参考文献
  • [LeetCode周赛复盘] 第 329 场周赛20230122
  • 数据结构进阶 哈希表
  • 【new操作符做了什么 —— js】
  • LeetCode刷题模版:171-174、179