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

mysql8.4+mysql router读写分离

以下为容器环境内搭建
准备工作:

拉取镜像:

镜像版本
mysql8.4
container-registry.oracle.com/mysql/community-router8.4

下载mysql_shell
mysql-shell-9.0.1-linux-glibc2.17-x86-64bit.tar.gz
下载地址: https://downloads.mysql.com/archives/shell/

参考
这里对这篇文章进行扩展, 容器环境及一些异常情况的处理

  1. 准备mysql配置文件
    注意点: sql-mode与老版本(sql_mode)不一样, binlog-ignore-db=mysql去掉

mysql_m1: master.cnf

[mysqld]
server-id=100gtid_mode=on
enforce-gtid-consistency=onexplicit_defaults_for_timestamp=true
lower_case_table_names=1
sql-mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION#binlog-ignore-db=mysql
max_allowed_packet=128M

mysql_s1: 配置文件(master.cnf)

[mysqld]
server-id=200gtid_mode=on
enforce-gtid-consistency=onexplicit_defaults_for_timestamp=true
lower_case_table_names=1
sql-mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION#binlog-ignore-db=mysql
max_allowed_packet=128M
# 以下容器需要在同一网段内, 否则创建
services:mysql_m1:image: mysql:8.4volumes:- ${PWD}/mysql-shell-9.0.1-linux-glibc2.17-x86-64bit:/mysql-shell- ${PWD}/mysql_m1/data:/var/lib/mysql- ${PWD}/mysql_m1/conf/master.conf:/etc/mysql/conf.d/master.cnfports :- "3306:3306"environment:- MYSQL_ROOT_PASSWORD=rootmysql_s1:image: mysql:8.4volumes:- ${PWD}/mysql_s1/data:/var/lib/mysql- ${PWD}/mysql_s1/conf/master.conf:/etc/mysql/conf.d/master.cnfports :- "3306:3306"environment:- MYSQL_ROOT_PASSWORD=root
  1. 通过docker-compose方式启动以上两个mysql容器,进入容器初始化ReplicaSet
    进入mysql shell所在目录,
    ./mysql_shell/bin/mysqlsh
./mysqlsh mysql://root@localhost:3310
Please provide the password for 'root@localhost:3310': ****
Save password for 'root@localhost:3310'? [Y]es/[N]o/Ne[v]er (default No): n
MySQL Shell 9.0.1Copyright (c) 2016, 2024, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its affiliates.
Other names may be trademarks of their respective owners.Type '\help' or '\?' for help; '\quit' to exit.
Creating a Classic session to 'root@localhost:3310'
Fetching global names for auto-completion... Press ^C to stop.
Your MySQL connection id is 8
Server version: 8.4.3 MySQL Community Server - GPL
No default schema selected; type \use <schema> to set one.MySQL  localhost:3310 ssl  SQL > MySQL  localhost:3310 ssl  SQL > \js
Switching to JavaScript mode...MySQL  localhost:3310 ssl  JS >

创建用户并给权限

create user rw_shell@'%' identified by 'xxx';
这里还需要设置权限(参考文章开头的链接)
MySQL  localhost:3310 ssl  JS > dba.configureReplicaSetInstance('rw_shell@localhost:3311', {"clusterAdmin": "rw_shell@'%'"})
// 输入登陆密码
创建ReplicaSet 报错: MySQL  localhost:3310 ssl  JS > rs = dba.createReplicaSet("prd_op_service")
A new replicaset with instance '4a64c4d2402e:3306' will be created.* Checking MySQL instance at 4a64c4d2402e:3306This instance reports its own address as 4a64c4d2402e:3306
4a64c4d2402e:3306: Instance configuration is suitable.
Dba.createReplicaSet: 4a64c4d2402e:3306: instance has binlog filters configured, but they are not supported in InnoDB ReplicaSets. (MYSQLSH 51150)报错: 
mysql_m1_1       [ERROR] [MY-013797] [Server] Option --authentication-policy is set to an invalid value. Please check if the specified authentication plugins are valid.
mysql_m1_1       [ERROR] [MY-013236] [Server] The designated data directory /var/lib/mysql/ is unusable. You can remove all files that the server added to it.
mysql_m1_1       [ERROR] [MY-010119] [Server] Aborting
mysql_m1_1       [System] [MY-015018] [Server] MySQL Server Initialization - end.
mysql_cluster_mysql_m1_1 exited with code 1

master.cnf配置文件里:
authentication_policy=mysql_native_password // 去掉
binlog-ignore-db=mysql // 去掉
sql_mode=xxx // 改为 => sql-mode 修改sql模式以支持full_group_by

  1. 创建ReplicaSet
 MySQL  localhost:3310 ssl  JS > var rs = dba.createReplicaSet("prd_op_service")
A new replicaset with instance '513842479f48:3306' will be created.* Checking MySQL instance at 513842479f48:3306This instance reports its own address as 513842479f48:3306
513842479f48:3306: Instance configuration is suitable.* Checking connectivity and SSL configuration...
* Updating metadata...ReplicaSet object successfully created for 513842479f48:3306.
Use rs.addInstance() to add more asynchronously replicated instances to this replicaset and rs.status() to check its status.MySQL  localhost  JS > rs.status()
{"replicaSet": {"name": "prd_op_service", "primary": "940d1a52cbdf:3306", "status": "AVAILABLE", "statusText": "All instances available.", "topology": {"940d1a52cbdf:3306": {"address": "940d1a52cbdf:3306", "instanceRole": "PRIMARY", "mode": "R/W", "status": "ONLINE"}}, "type": "ASYNC"}
}
  1. 增加从节点, addInstance后,需要去手动重启从节点
 MySQL  localhost  JS > rs.addInstance('mysql_s1:3306')Adding instance to the replicaset...* Performing validation checksThis instance reports its own address as 54ef15541a78:3306
54ef15541a78:3306: Instance configuration is suitable.* Checking async replication topology...* Checking connectivity and SSL configuration...* Checking transaction state of the instance...WARNING: A GTID set check of the MySQL instance at '54ef15541a78:3306' determined that it contains transactions that do not originate from the replicaset, which must be discarded before it can join the replicaset.Instance '54ef15541a78:3306' has the following errant GTIDs that do not exist in the replicaset:6ce93fa1-a31e-11ef-8917-0242ac190002:1-7WARNING: Discarding these extra GTID events can either be done manually or by completely overwriting the state of '54ef15541a78:3306' with a physical snapshot from an existing replicaset member. To use this method by default, set the 'recoveryMethod' option to 'clone'.Having extra GTID events is not expected, and it is recommended to investigate this further and ensure that the data can be removed prior to choosing the clone recovery method.Please select a recovery method [C]lone/[A]bort (default Abort): c
* Updating topology
Monitoring Clone based state recovery of the new member. Press ^C to abort the operation.
Clone based state recovery is now in progress.NOTE: A server restart is expected to happen as part of the clone process. If the
server does not support the RESTART command or does not come back after a
while, you may need to manually start it back.* Waiting for clone to finish...
NOTE: 54ef15541a78:3306 is being cloned from 940d1a52cbdf:3306
** Stage DROP DATA: Completed
** Clone Transfer  FILE COPY  ============================================================    0%  In ProgressPAGE COPY  ============================================================    0%  Not StartedREDO COPY  ============================================================    0%  Not StartedNOTE: 54ef15541a78:3306 is shutting down...* Waiting for server restart... timeout 
WARNING: Clone process appears to have finished and tried to restart the MySQL server, but it has not yet started back up.Please make sure the MySQL server at '54ef15541a78:3306' is properly restarted. The operation will be reverted, but you may retry adding the instance after restarting it. 
ERROR: Error adding instance to replicaset: MYSQLSH 51156: Timeout waiting for server to restart
Reverting topology changes...
ERROR: Error while reverting replication changes: MySQL Error 2013: Lost connection to MySQL server during queryChanges successfully reverted.
ERROR: 54ef15541a78:3306 could not be added to the replicaset
ReplicaSet.addInstance: Timeout waiting for server to restart (MYSQLSH 51156)MySQL  localhost  JS > rs.status();
{"replicaSet": {"name": "prd_op_service", "primary": "940d1a52cbdf:3306", "status": "AVAILABLE", "statusText": "All instances available.", "topology": {"54ef15541a78:3306": {"address": "54ef15541a78:3306", "instanceRole": "SECONDARY", "mode": "R/O", "replication": {"applierStatus": "APPLIED_ALL", "applierThreadState": "Waiting for an event from Coordinator", "applierWorkerThreads": 4, "receiverStatus": "ON", "receiverThreadState": "Waiting for source to send event", "replicationLag": null, "replicationSsl": "TLS_AES_128_GCM_SHA256 TLSv1.3", "replicationSslMode": "REQUIRED"}, "status": "ONLINE"}, "940d1a52cbdf:3306": {"address": "940d1a52cbdf:3306", "instanceRole": "PRIMARY", "mode": "R/W", "status": "ONLINE"}}, "type": "ASYNC"}
}
  1. 启动路由节点
    参考 https://dev.mysql.com/doc/mysql-router/8.4/en/mysql-router-installation-docker.html
    访问6450端口,数据查询正常(连接从节点),开启事务访问正常(进入主节点)
测试路由是否生效./mysqlsh -u rw_shell -P 6450 -pMySQL  localhost:6450 ssl  SQL > select @@hostname;
+--------------+
| @@hostname   |
+--------------+
| 54ef15541a78 | // 从节点
+--------------+
1 row in set (0.0011 sec)
Statement ID: 3736MySQL  localhost:6450 ssl  SQL > begin; // 事务开始
Query OK, 0 rows affected (0.0036 sec)
Statement ID: 6895MySQL  localhost:6450 ssl  ★  SQL > select @@hostname;
+--------------+
| @@hostname   |
+--------------+
| 940d1a52cbdf | // 主节点
+--------------+
1 row in set (0.0006 sec)
Statement ID: 6967MySQL  localhost:6450 ssl  ★  SQL > commit; // 提交
Query OK, 0 rows affected (0.0006 sec)
Statement ID: 7407MySQL  localhost:6450 ssl  SQL > select @@hostname;
+--------------+
| @@hostname   |
+--------------+
| 54ef15541a78 | // 从节点
+--------------+
1 row in set (0.0011 sec)
Statement ID: 4408
  1. 启动应用服务连接mysql_router

连接mysql_router:6450端口报错:

Caused by: java.sql.SQLNonTransientConnectionException: Public Key Retrieval is not allowed
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:110)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:828)
at com.mysql.cj.jdbc.ConnectionImpl.(ConnectionImpl.java:448)
at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:241)
at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:198)

连接url加上allowPublicKeyRetrieval参数

Caused by: java.sql.SQLNonTransientConnectionException: Could not create connection to database server.
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:110)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:89)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:63)
at com.mysql.cj.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:1001)
at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:818)
…略
Caused by: java.lang.ArrayIndexOutOfBoundsException: Index 8 out of bounds for length 7
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:110)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:89)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:63)

连接url加上trackSessionState参数 参考
最终
jdbc:mysql://xxx:6450/xxx?allowPublicKeyRetrieval=true&trackSessionState=true

相关文章:

mysql8.4+mysql router读写分离

以下为容器环境内搭建 准备工作: 拉取镜像: 镜像版本mysql8.4container-registry.oracle.com/mysql/community-router8.4 下载mysql_shell mysql-shell-9.0.1-linux-glibc2.17-x86-64bit.tar.gz 下载地址: https://downloads.mysql.com/archives/shell/ 参考 这里对这篇文章…...

鸿蒙NEXT开发-用户通知服务的封装和文件下载通知

注意&#xff1a;博主有个鸿蒙专栏&#xff0c;里面从上到下有关于鸿蒙next的教学文档&#xff0c;大家感兴趣可以学习下 如果大家觉得博主文章写的好的话&#xff0c;可以点下关注&#xff0c;博主会一直更新鸿蒙next相关知识 专栏地址: https://blog.csdn.net/qq_56760790/…...

RHCE——系统的延迟任务及定时任务

延迟任务的发起 在系统中我们可以使用 at 命令来发起延迟任务 at 命令执行是调用的是 atd 服务&#xff0c;即使系统最小化安装 atd 也会被安装到系统中 at 任务信息存放在系统中 /var/spool/at 目录中 at 任务的日志文件被存放到 /var/log/cron 中 at 任务执行时如果遇…...

ForEach刷新UI机制

官网地址&#xff1a;ForEach 在ArkUI中&#xff0c;提供了ForEach循环语句&#xff0c;用来初始化一个列表数据&#xff0c;我们知道&#xff0c;当ForEach中的数组发生变化时&#xff0c;会引起UI的刷新&#xff0c;但是究竟如何变化&#xff0c;会引起UI怎样的刷新&#xf…...

机器学习(贝叶斯算法,决策树)

朴素贝叶斯分类 贝叶斯分类理论 假设现有两个数据集&#xff0c;分为两类 我们现在用p1(x,y)表示数据点(x,y)属于类别1(图中红色圆点表示的类别)的概率&#xff0c;用p2(x,y)表示数据点(x,y)属于类别2(图中蓝色三角形表示的类别)的概率&#xff0c;那么对于一个新数据点(x,y)…...

实验十三 生态安全评价

1 背景及目的 生态安全是生态系统完整性和健康性的整体反映&#xff0c;完整健康的生态系统具有调节气候净化污染、涵养水源、保持水土、防风固沙、减轻灾害、保护生物多样性等功能。维护生态安全对于人类生产、生活、健康及可持续发展至关重要。随着城市化进程的不断推进&…...

二级等保要求及设备有哪些?

《网络安全法》规定我国信息系统实际等级保护制度&#xff0c;不同等保等级要求不同&#xff1a; 二级等保&#xff08;指导保护级&#xff09;&#xff1a;等级保护对象受到破坏后&#xff0c;会对公民、法人和其他组织的合法权益产生严重损害&#xff0c;或者对社会秩序和公…...

无人机的动力系统节能——CKESC电调小课堂12

1.优化电机和螺旋桨配置 精准匹配&#xff1a;根据无人机的设计用途和负载要求&#xff0c;精确选择电机和螺旋桨。确保电机的功率、扭矩等参数与螺旋桨的尺寸、螺距等完美匹配。例如&#xff0c;对于轻型航拍无人机&#xff0c;选用功率合适的小尺寸电机搭配高效的小螺旋桨&a…...

人机打怪小游戏(非常人机)

按q攻击 按箭头进行控制 玩家是 怪是* 攻击是^ ​ ​ #include<bits/stdc.h> #include<Windows.h> #include<conio.h> #define fr(i,a,b) for(int ia;i<b;i) #define rd(a,b) rand()%(b-a1)a using namespace std; int x16,y21,dx[4]{-1,0,1,0},dy[4]{0,…...

SpringBoot 集成 Sharding-JDBC(一):数据分片

在深入探讨 Sharding-JDBC 之前&#xff0c;建议读者先了解数据库分库分表的基本概念和应用场景。如果您还没有阅读过相关的内容&#xff0c;可以先阅读我们之前的文章&#xff1a; 关系型数据库海量数据存储策略-CSDN博客 这篇文章将帮助您更好地理解分库分表的基本原理和实现…...

django-ninja 实现cors跨域请求

要在Django-Ninja项目中实现跨域&#xff08;CORS&#xff09;&#xff0c;你可以使用django-cors-headers库&#xff0c;这是一个专门用于处理跨域资源共享&#xff08;CORS&#xff09;问题的Django应用程序。以下是具体的步骤和配置&#xff1a; 安装依赖&#xff1a; 使用p…...

【论文阅读】InstructPix2Pix: Learning to Follow Image Editing Instructions

摘要&#xff1a; 提出了一种方法&#xff0c;用于教导生成模型根据人类编写的指令进行图像编辑&#xff1a;给定一张输入图像和一条书面指令&#xff0c;模型按照指令对图像进行编辑。 由于为此任务获取大规模训练数据非常困难&#xff0c;我们提出了一种生成配对数据集的方…...

常用在汽车PKE无钥匙进入系统的高度集成SOC芯片:CSM2433

CSM2433是一款集成2.4GHz频段发射器、125KHz接收器和8位RISC&#xff08;精简指令集&#xff09;MCU的SOC芯片&#xff0c;用在汽车PKE无钥匙进入系统里。 什么是汽车PKE无钥匙进入系统&#xff1f; 无钥匙进入系统具有无钥匙进入并且启动的功能&#xff0c;英文名称是PKE&…...

【第四课】rust声明式宏理解与实战

目录 前言 理解宏 实战宏 前言 上一课在介绍vector时&#xff0c;我们再一次提到了rust中的宏&#xff0c;在初始化vector时使用了vec!宏&#xff0c;当时补了一句有机会会好好说明一下rust中的宏&#xff0c;并且写一个hashmap宏来初始化hashmap。想了想一直介绍基本语法还…...

渗透测试--Linux下的文件传输方法

渗透测试过程中&#xff0c;我们经常会需要文件传输&#xff0c;本文主要探讨Linux主机上我们对文件传输的方法。 编码方式 Linux 检查MD5 md5sum id_rsa Linux Base64 编码/解码 编码 cat id_rsa |base64 -w 0;echo 解码 echo -n LS0tLS1CRUdJTiBPUEVOU1NIIFBSSVZBVE…...

浅议Flink中的通讯工具: Akka

在Flink中&#xff0c;各个组件之间需要频繁交换数据和控制信息。Flink选择了基于Actor模型的Akka框架作为通信基础。 Akka是什么 Actor模型 Actor模型是用于单个进程中并发的场景。 在Actor模型中&#xff1a; ActorSystem负责管理actor生命周期 将每个实体视为独立的 Ac…...

基于YOLOv8深度学习的独居老人情感状态监护系统(PyQt5界面+数据集+训练代码)

本研究提出了一种创新的独居老人情感状态监护系统&#xff0c;基于YOLOV8深度学习模型&#xff0c;旨在通过对老年人面部表情的实时监测与分析&#xff0c;来精准识别其情感变化&#xff0c;从而提高独居老人的生活质量&#xff0c;确保其心理健康。本系统通过整合先进的YOLOV8…...

Qt添加外部库:静态库和动态库,批量添加头文件

Qt添加外部库需要知道库文件的位置才能正确链接&#xff0c;如果是静态库&#xff0c;要确保LIBS变量中包含正确的库文件路径和库文件名;如果是动态库&#xff0c;除了库路径外&#xff0c;还需要考虑动态库的加载路径。在 Windows 下&#xff0c;可以将动态库所在路径添加到系…...

Unity类银河战士恶魔城学习总结(P132 Merge skill tree with skill Manager 把技能树和冲刺技能相组合)

【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili 教程源地址&#xff1a;https://www.udemy.com/course/2d-rpg-alexdev/ 本章节实现了解锁技能后才可以使用技能&#xff0c;先完成了冲刺技能的锁定解锁 Dash_Skill.cs using System.Collections; using System…...

Docker入门之Windows安装Docker初体验

在之前我们认识了docker的容器&#xff0c;了解了docker的相关概念&#xff1a;镜像&#xff0c;容器&#xff0c;仓库&#xff1a;面试官让你介绍一下docker&#xff0c;别再说不知道了 之后又带大家动手体验了一下docker从零开始玩转 Docker&#xff1a;一站式入门指南&#…...

HTML 列表、表格、表单

1 列表标签 作用&#xff1a;布局内容排列整齐的区域 列表分类&#xff1a;无序列表、有序列表、定义列表。 例如&#xff1a; 1.1 无序列表 标签&#xff1a;ul 嵌套 li&#xff0c;ul是无序列表&#xff0c;li是列表条目。 注意事项&#xff1a; ul 标签里面只能包裹 li…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...

JAVA后端开发——多租户

数据隔离是多租户系统中的核心概念&#xff0c;确保一个租户&#xff08;在这个系统中可能是一个公司或一个独立的客户&#xff09;的数据对其他租户是不可见的。在 RuoYi 框架&#xff08;您当前项目所使用的基础框架&#xff09;中&#xff0c;这通常是通过在数据表中增加一个…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲

文章目录 前言第一部分&#xff1a;体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分&#xff1a;体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

Netty从入门到进阶(二)

二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架&#xff0c;用于…...

苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会

在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...

《Docker》架构

文章目录 架构模式单机架构应用数据分离架构应用服务器集群架构读写分离/主从分离架构冷热分离架构垂直分库架构微服务架构容器编排架构什么是容器&#xff0c;docker&#xff0c;镜像&#xff0c;k8s 架构模式 单机架构 单机架构其实就是应用服务器和单机服务器都部署在同一…...

JS红宝书笔记 - 3.3 变量

要定义变量&#xff0c;可以使用var操作符&#xff0c;后跟变量名 ES实现变量初始化&#xff0c;因此可以同时定义变量并设置它的值 使用var操作符定义的变量会成为包含它的函数的局部变量。 在函数内定义变量时省略var操作符&#xff0c;可以创建一个全局变量 如果需要定义…...

leetcode73-矩阵置零

leetcode 73 思路 记录 0 元素的位置&#xff1a;遍历整个矩阵&#xff0c;找出所有值为 0 的元素&#xff0c;并将它们的坐标记录在数组zeroPosition中置零操作&#xff1a;遍历记录的所有 0 元素位置&#xff0c;将每个位置对应的行和列的所有元素置为 0 具体步骤 初始化…...

二叉树-144.二叉树的前序遍历-力扣(LeetCode)

一、题目解析 对于递归方法的前序遍历十分简单&#xff0c;但对于一位合格的程序猿而言&#xff0c;需要掌握将递归转化为非递归的能力&#xff0c;毕竟递归调用的时候会调用大量的栈帧&#xff0c;存在栈溢出风险。 二、算法原理 递归调用本质是系统建立栈帧&#xff0c;而非…...