【SpringCloud】创建新工程

前言

本文使用的是jdk17,mysql8。

以下用两个服务做演示:

订单服务:提供订单ID,获取订单详细信息。

商品服务:提供商品ID,获取商品详细信息。

对于订单服务和商品服务分别建立数据库:

-- 订单服务

-- 建库
create database if not exists cloud_order charset utf8mb4;
use cloud_order;
-- 订单表
DROP TABLE IF EXISTS order_detail;
CREATE TABLE order_detail (
        `id` INT NOT NULL AUTO_INCREMENT COMMENT '订单id',
        `user_id` BIGINT ( 20 ) NOT NULL COMMENT '用户ID',
        `product_id` BIGINT ( 20 ) NULL COMMENT '产品id',
        `num` INT ( 10 ) NULL DEFAULT 0 COMMENT '下单数量',
        `price` BIGINT ( 20 ) NOT NULL COMMENT '实付款',
        `delete_flag` TINYINT ( 4 ) NULL DEFAULT 0,
        `create_time` DATETIME DEFAULT now(),
        `update_time` DATETIME DEFAULT now(),
PRIMARY KEY ( id )) ENGINE = INNODB DEFAULT CHARACTER 
SET = utf8mb4 COMMENT = '订单表';

-- 数据初始化
insert into order_detail (user_id,product_id,num,price)
values
(2001, 1001,1,99), (2002, 1002,1,30), (2001, 1003,1,40),
(2003, 1004,3,58), (2004, 1005,7,85), (2005, 1006,7,94);


-- 产品服务
create database if not exists cloud_product charset utf8mb4;

-- 产品表
use cloud_product;
DROP TABLE IF EXISTS product_detail;
CREATE TABLE product_detail (
        `id` INT NOT NULL AUTO_INCREMENT COMMENT '产品id',
        `product_name` varchar ( 128 ) NULL COMMENT '产品名称',
        `product_price` BIGINT ( 20 ) NOT NULL COMMENT '产品价格',
        `state` TINYINT ( 4 ) NULL DEFAULT 0 COMMENT '产品状态 0-有效 1-下架',
        `create_time` DATETIME DEFAULT now(),
        `update_time` DATETIME DEFAULT now(),
PRIMARY KEY ( id )) ENGINE = INNODB DEFAULT CHARACTER 
SET = utf8mb4 COMMENT = '产品表';

-- 数据初始化
insert into product_detail (id, product_name,product_price,state)
values
(1001,"T恤", 101, 0), (1002, "短袖",30, 0), (1003, "短裤",44, 0), 
(1004, "卫衣",58, 0), (1005, "马甲",98, 0),(1006,"羽绒服", 101, 0), 
(1007, "冲锋衣",30, 0), (1008, "袜子",44, 0), (1009, "鞋子",58, 0),
(10010, "毛衣",98, 0);

服务拆分

微服务到底多小才算“微”,这个在业界并没有明确的标准。微服务并不是越小越好,服务越小,微服务架构的优点和缺点都会越来越明显。

服务越小,微服务的独立性就会越来越高,但同时,微服务的数量也会越多,管理这些微服务的难度也会提高。所以服务拆分也要考虑场景。

服务拆分原则

单一职责原则

在微服务架构中意味着每个微服务应该只负责一个功能或业务领域,每个服务应该有清晰的定义和边界,只关注自己的特定业务领域。

服务自治

指的是每个微服务都应该具备高度自治的能力,即每个服务要能做到独立开发、独立测试、独立构建、独立部署、独立运行。

单向依赖

意味着微服务之间需要做到单向依赖,严禁循环依赖和双向依赖。循环依赖示例:A -> B -> C -> A;双向依赖示例:A -> B, B -> A。如果一些场景确实无法避免循环依赖或者双向依赖,可以考虑使用消息队列等其他方式来实现。

工程搭建

这里使用的父子项目来创建。

创建父项目

选择Maven项目

一路next完成即可。

创建完成后,删除所有的代码,仅保留pom.xml文件

完善pom文件

使用 properties 来统一管理版本号,使用 dependencyManagement 来管理依赖,父工程的打包方式为 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>

    <groupId>org.example</groupId>
    <artifactId>spring-cloud-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.1.6</version>
        <relativePath/>
    </parent>
    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <java.version>17</java.version>
        <mybatis.version>3.0.3</mybatis.version>
        <mysql.version>8.0.33</mysql.version>
        <spring-cloud.version>2022.0.3</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <!-- 使用lombok基本都会使用到,所以直接引入到项目,被子项目继承 -->
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis.version}</version>
            </dependency>
            <dependency>
                <groupId>com.mysql</groupId>
                <artifactId>mysql-connector-j</artifactId>
                <version>${mysql.version}</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter-test</artifactId>
                <version>${mybatis.version}</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

dependencies:将所依赖的 JAR 直接加到项目中。子项目也会继承该依赖。

dependencyManagement:只是声明依赖,并不实现 JAR 包引入。如果子项目需要用到相关依赖,需要显式声明。如果子项目没有指定具体版本,会从父项目中读取 version。如果子项目中指定了版本号,就会使用子项目中指定的 JAR 版本。此外,父工程的打包方式应该是 pom,不是 jar,这里需要手动使用 packaging 来声明。

创建子项目

创建另一个项目也是同理。

创建完两个子项目后,观察父项目的pom文件,这里会自动添加两个模块。

完善子项目

pom文件

在两个子项目中的pom文件中分别添加我们所需要依赖。

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

下面是order-service完整的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>spring-cloud-demo</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>order-service</artifactId>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

启动类

创建好包和启动类。

order-service:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }
}

product-service:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ProductServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProductServiceApplication.class, args);
    }
}

配置文件

order_service:

server:
  port: 8240
spring:
  datasource:
    url: jdbc:mysql://ip:端口号/cloud_order?characterEncoding=utf8&useSSL=false
    username: 用户名
    password: 密码
    driver-class-name: com.mysql.cj.jdbc.Driver

# 设置 Mybatis 的 xml 保存路径
mybatis:
  configuration: # 配置打印 MyBatis 执行的 SQL
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: true  #自动驼峰转换
    
# 配置打印 MyBatis 执行的 SQL
logging:
  file:
    name: logs/springboot.log
  logback:
    rollingpolicy:
      max-file-size: 1KB
      file-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}.%i
  level:
    com:
      example:
        demo: debug

product_service:

server:
  port: 8250
spring:
  datasource:
    url: jdbc:mysql://ip:端口号/cloud_product?characterEncoding=utf8&useSSL=false
    username: 用户名
    password: 密码
    driver-class-name: com.mysql.cj.jdbc.Driver

# 设置 Mybatis 的 xml 保存路径
mybatis:
  configuration: # 配置打印 MyBatis 执行的 SQL
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: true  #自动驼峰转换
    
# 配置打印 MyBatis 执行的 SQL
logging:
  file:
    name: logs/springboot.log
  logback:
    rollingpolicy:
      max-file-size: 1KB
      file-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}.%i
  level:
    com:
      example:
        demo: debug

业务代码

对于order_service:

controller层:

package com.demo.order.controller;

import com.demo.order.model.OrderInfo;
import com.demo.order.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/order")
@RestController
public class OrderController {
    @Autowired
    private OrderService orderService;

    @RequestMapping("/{orderId}")
    public OrderInfo getOrderById(@PathVariable("orderId") Integer orderId){
        return orderService.selectOrderById(orderId);
    }
}

service层:

package com.demo.order.service;

import com.demo.order.mapper.OrderMapper;
import com.demo.order.model.OrderInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class OrderService {
    @Autowired
    private OrderMapper orderMapper;

    public OrderInfo selectOrderById(Integer orderId){
        OrderInfo orderInfo = orderMapper.selectOrderById(orderId);
        return orderInfo;
    }
}

model层:

package com.demo.order.model;

import lombok.Data;

import java.util.Date;

@Data
public class OrderInfo {
    private Integer id;
    private Integer userId;
    private Integer productId;
    private Integer num;
    private Integer price;
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;
}

mapper层:

package com.demo.order.mapper;

import com.demo.order.model.OrderInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface OrderMapper {
    @Select("select * from order_detail where id=#{orderId}")
    OrderInfo selectOrderById(Integer orderId);
}

启动后查看:

对于product-service:

controller层:

package com.demo.product.com.demo.controller;

import com.demo.product.com.demo.model.ProductInfo;
import com.demo.product.com.demo.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/product")
@RestController
public class ProductController {
    @Autowired 
    ProductService productService;
    @RequestMapping("/{productId}")
    public ProductInfo getProductById(@PathVariable("productId") Integer productId) {
        return productService.selectProductById(productId);
    }
}

service层:

package com.demo.product.com.demo.service;

import com.demo.product.com.demo.mapper.ProductMapper;
import com.demo.product.com.demo.model.ProductInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class ProductService {
    @Autowired
    private ProductMapper productMapper;
    public ProductInfo selectProductById(Integer productId) {
        return productMapper.selectProductById(productId);
    }
}

model层:

package com.demo.product.com.demo.model;

import lombok.Data;
import java.util.Date;
@Data
public class ProductInfo {
    private Integer id;
    private String productName;
    private Integer productPrice;
    private Integer state;
    private Date createTime;
    private Date updateTime;
}

mapper层:

package com.demo.product.com.demo.mapper;

import com.demo.product.com.demo.model.ProductInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface ProductMapper {
    @Select("select * from product_detail where id=#{id}")
    ProductInfo selectProductById(Integer id);
}

启动后查看:

 

远程调用

需求:根据订单查询订单信息时,要使用订单信息中的产品ID获取产品详细信息。

实现思路:order-service服务像product-service服务发送一个http请求,把得到的结果和订单结合一起返回。

实现方法:使用Spring提供的RestTemplate

修改代码

在model中添加product实体类。把product-service中的product复制过去即可。

同时在order-service中的order实体类中添加上product最为字段。

在order-server中配置文件中注入RestTemplate

@Configuration
public class BeanConfig {
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

修改order-server中的OrderService

package com.demo.order.service;

import com.demo.order.mapper.OrderMapper;
import com.demo.order.model.OrderInfo;
import com.demo.order.model.ProductInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class OrderService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private RestTemplate restTemplate;

    public OrderInfo selectOrderById(Integer orderId){
        OrderInfo orderInfo = orderMapper.selectOrderById(orderId);
        String url = "http://127.0.0.1:8350/product/"+ orderInfo.getProductId();
        ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);
        orderInfo.setProductInfo(productInfo);
        return orderInfo;
    }
}

测试

启动两个服务。

 

上面的代码是最简单的实现,代码还存在很多问题,后续还需要继续解决。

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

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

相关文章

一款不写代码的开源爬虫工具!!【送源码】

爬虫&#xff0c;也被称为网络爬虫或网络蜘蛛&#xff0c;是一种自动化的网络机器人&#xff0c;其主要功能是按照一定的规则&#xff0c;自动浏览互联网并从网页中提取信息。 作为一个开发人员&#xff0c;相信大家都尝试过写一些爬虫&#xff0c;合理的利用一些爬虫工具&…

【代码随想录】【算法训练营】【第35天】[134]加油站 [135]分发糖果 [860]柠檬水找零 [406]根据身高重建队列

前言 思路及算法思维&#xff0c;指路 代码随想录。 题目来自 LeetCode。 day 35&#xff0c;连休两天~ 题目详情 [134] 加油站 题目描述 134 加油站 解题思路 前提&#xff1a;数组 思路&#xff1a;全局贪心算法&#xff1a;最小累加剩余汽油为负数&#xff0c;说明…

博客没人看啊?我分析是这些原因

1.封面 主题封面还是个性化封面&#xff1f;主题封面对系列化很友好&#xff0c;如下图左&#xff1a; 在目录中什么主题一目了然&#xff0c;个性化封面在目录中就略显杂乱。但是通过观察CSDN主页发现热榜文章清一色个性化封面。如果使文字封面就会显得很无聊。 所以从提高浏…

Orange_Pi_AIpro运行蜂鸟RISC-V仿真

Orange_Pi_AIpro运行蜂鸟RISC-V仿真 突发奇想&#xff0c;试一试Orange Pi AIpro上运行蜂鸟RISC-V的仿真。 准备 默认已经有一个Orange Pi AIpro&#xff0c;并且对设备进行一定的初始化配置&#xff0c;可以参考上一篇博文开源硬件初识——Orange Pi AIpro&#xff08;8T&a…

零代码本地搭建AI大模型,详细教程!普通电脑也能流畅运行,中文回答速度快,回答质量高

这篇教程主要解决&#xff1a; 1). 有些读者朋友&#xff0c;电脑配置不高&#xff0c;比如电脑没有配置GPU显卡&#xff0c;还想在本地使用AI&#xff1b; 2). Llama3回答中文问题欠佳&#xff0c;想安装一个回答中文问题更强的AI大模型。 3). 想成为AI开发者&#xff0c;开…

运行时类型识别RTTI(typeid dynamic_cast)和虚函数机制的关系

1.typeid 2.dynamic_cast 指针类型决定了可以操作的内存范围大小 子类指针转化为父类类型的指针的一般是合法的&#xff1a; 父类的指针类型转化为子类类型指针&#xff0c;超过合法操作范围&#xff0c;不安全 两种转换&#xff1a;编译期的转换&#xff0c;运行时的转化 编译…

【Java】图书管理系统-控制台输出

项目原码压缩包在我主页的资源中免费领取。&#xff08;在IDEA中运行&#xff0c;启动类在src -> Main 中运行&#xff09; 图书管理系统 设计一个简单的控制台输出的图书管理系统&#xff0c;我们首先需要明确其基本功能、设计内容以及设计要求。这个系统可以包括以下几个…

解决Windows中端口占用导致服务启动失败

解决Windows中端口占用导致服务启动失败 在cmd窗口中使用netstat -ano | findstr "3306"来查看哪个线程占用了3306端口。 下面的图片里面表示一个pid为5196的进程占用了端口 接着可以在cmd窗口中使用tasklist | findstr "5196" 根据pid查询进程名称 通过…

LVS三种负载均衡模式:NAT、Tunneling和DR的技术对比

1. LVS-NAT 模式的特性 IP使用&#xff1a;RS&#xff08;Real Server&#xff09;应使用私有地址&#xff0c;RS的网关必须指向DIP&#xff08;Director IP&#xff09;。网络范围&#xff1a;DIP和RIP必须在同一个网段内。数据包处理&#xff1a;请求和响应报文都需要经过Di…

[DDR4] DDR1 ~ DDR4 发展史导论

依公知及经验整理&#xff0c;原创保护&#xff0c;禁止转载。 专栏 《深入理解DDR4》 内存和硬盘是电脑的左膀右臂&#xff0c; 挑起存储的大梁。因为内存的存取速度超凡地快&#xff0c; 但内存上的数据掉电又会丢失&#xff0c;一直其中缓存的作用&#xff0c;就像是我们的工…

基于System-Verilog的FPGA设计与仿真

一、System-Verilog System Verilog的发展 SystemVerilog 的出现是为了因应日益复杂的数位电路设计和验证需求。虽然Verilog HDL 在早期的数位电路设计中得到了广泛应用&#xff0c;但随着技术的发展和电路复杂度的增加&#xff0c;Verilog HDL 在某些方面已经显得有些不足以满…

线稳源极跟随 线性电源前端降压

功率MOSFET线性电源涉及跟随.ms14 根本原理是Vgs对Id的控制&#xff0c;Vgs越大&#xff0c;Id越大&#xff0c;反之亦然。 观察转移特性曲线&#xff0c;结合接线图可知&#xff0c;电路稳定后&#xff0c;如果负载电阻增大&#xff0c;则Vsgnd增大&#xff0c;由于Vggnd有稳…

【数据挖掘】机器学习中相似性度量方法-余弦相似度

写在前面&#xff1a; 首先感谢兄弟们的订阅&#xff0c;让我有创作的动力&#xff0c;在创作过程我会尽最大能力&#xff0c;保证作品的质量&#xff0c;如果有问题&#xff0c;可以私信我&#xff0c;让我们携手共进&#xff0c;共创辉煌。 路虽远&#xff0c;行则将至&#…

在k8s上部署一个简单的应用

部署一个简单的应用 实验目标&#xff1a; 部署一个简单的 web 应用&#xff0c;比如 Nginx 或者一个自定义的 Node.js 应用。 实验步骤&#xff1a; 创建一个 Deployment。创建一个 Service 来暴露应用。验证应用是否可以通过 Service 访问。 今天我们来做一下昨天分享的可…

【TB作品】STM32F102C8T6单片机,PWM发生器

硬件&#xff1a; STM32F102C8T6核心板&#xff0c;按键&#xff0c;0.96 OLED显示屏。 软件&#xff1a; 1、硬件启动触发单片机输出PWM&#xff0c;未触发之前PWM输出为低电平。 2、按键修改PWM的变化模式、变化时间长度、占空比上下限。 3、输出的PWM是固定的10kHZ的。 4、变…

王思聪日本街头在被偶遇

王思聪日本街头再被偶遇&#xff0c;甜蜜约会日常成网友热议焦点近日&#xff0c;有网友在日本街头再次偶遇了“国民老公”王思聪&#xff0c;这次他不仅携带着一位美丽的女友&#xff0c;还展现出了两人之间亲密无间的互动&#xff0c;让不少网友感叹&#xff1a;这真的是每天…

Kafka 如何保证消息顺序及其实现示例

Kafka 如何保证消息顺序及其实现示例 Kafka 保证消息顺序的机制主要依赖于分区&#xff08;Partition&#xff09;的概念。在 Kafka 中&#xff0c;消息的顺序保证是以分区为单位的。下面是 Kafka 如何保证消息顺序的详细解释&#xff1a; ⭕分区内消息顺序 顺序写入&#…

掌握特劳特定位理论核心,明晰企业战略定位之重

在当今瞬息万变的市场环境中&#xff0c;企业战略定位的重要性日益凸显。它不仅是企业在激烈竞争中保持优势的关键&#xff0c;更是企业实现长期可持续发展的基石。 哈佛大学战略学教授迈克尔波特&#xff08;Michael Porter&#xff09;指出战略就是形成一套独具的运营活动&a…

前端组件样式穿透修改

背景&#xff1a; 在style经常用scoped属性实现组件的私有化时&#xff0c;要改变element-ui某个深层元素&#xff08;例如.el-input__inner&#xff09;或其他深层样式&#xff0c; 但是element-ui 并没有提供修改的接口。 这时&#xff0c;就是需要手动修改样式。 解决方法…

Oracle备份失败处理,看这一篇就够了!

作者&#xff1a;IT邦德 中国DBA联盟(ACDU)成员&#xff0c;10余年DBA工作经验&#xff0c; Oracle、PostgreSQL ACE CSDN博客专家及B站知名UP主&#xff0c;全网粉丝10万 擅长主流Oracle、MySQL、PG、高斯及Greenplum备份恢复&#xff0c; 安装迁移&#xff0c;性能优化、故障…