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

KingbaseES读写分离高可用集群扩容、备库重建与故障切换实战

文章目录

  • 一、安装包下载及环境部署
  • 二、KingbaseES V9R3C18 读写分离集群环境信息
    • 2.1 环境规划
    • 2.2 系统环境
    • 2.3 安装介质
  • 三、读写分离集群扩容
    • 3.1 新节点准备
    • 3.2 新节点配置
      • 3.2.1 配置主机名
      • 3.2.2 配置 sysctl 参数
      • 3.2.3 配置 SSH 服务参数
      • 3.2.4 生成 SSH key
      • 3.2.5 配置 known_hosts
      • 3.2.6 配置三节点 SSH 互信
    • 3.3 新节点扩容前准备
      • 3.3.1 检查主节点位置
      • 3.3.2 准备 node3 临时扩容目录
      • 3.3.3 准备扩容节点临时扩容目录
      • 3.3.4 扩容前检查
    • 3.4 开始扩容
  • 四、重建备库的克隆同步速率控制
    • 4.1 重建前状态确认
      • 4.1.1 集群查看状态
      • 4.1.2 在主节点写入测试数据
      • 4.1.3 配置环境变量
    • 4.2 停止待重建备库
    • 4.3 清理旧备库环境
      • 4.3.1 检查复制槽
      • 4.3.2 移动旧数据目录
    • 4.4 开始重建
      • 4.4.1 执行限速 clone(32mb/s)
      • 4.4.2 启动备库
    • 4.5 验证备库
    • 小结
  • 五、主库故障下并行检测
    • 5.1 环境准备
      • 5.1.1 确认当前集群状态
      • 5.1.2 打开HA日志观察窗口
    • 5.2 故障模拟
    • 5.3 故障恢复
      • 5.3.1 恢复启动ha组件
      • 5.3.2 最终验证
    • 小结
  • 六、选举与升主流程优化
    • 6.1 选举策略优化目标
    • 6.2 检查状态
    • 6.3 策略配置
      • 6.3.1 在 node1 上降低候选优先级
      • 6.3.2 重新注册 node1 的优先级
      • 6.3.3 在 node3 上提高候选优先级
      • 6.3.4 重新注册 node3 的优先级
      • 6.3.5 在node2验证优先级是否生效
    • 6.4 模拟故障测试
      • 6.4.1 在 node3 打开日志观察窗口
      • 6.4.2 模拟 node2 主库故障
      • 6.4.3 观察选举与升主日志
      • 6.4.4 验证 node3 是否成为新主库
    • 小结
  • 总结

一、安装包下载及环境部署

https://www.kingbase.com.cn/download.html

下载测试安装包并且进行部署

详细部署流程见:https://blog.csdn.net/qq_46302361/article/details/162045963

二、KingbaseES V9R3C18 读写分离集群环境信息

2.1 环境规划

角色主机名IP 地址网卡说明
主库node1192.168.40.112ens192当前 primary,持有 VIP
备库node2192.168.40.113ens192standby,从 node1 流复制
VIP-192.168.40.115/24ens192对外访问入口
网关/仲裁检测地址-192.168.40.2ens192trusted_servers

2.2 系统环境

项目node1node2
操作系统UOS Server 20UOS Server 20
内核版本4.19.90-2305.1.0.0199.56.uel20.x86_644.19.90-2305.1.0.0199.56.uel20.x86_64
CPUAMD Ryzen 7 5825U with Radeon GraphicsAMD Ryzen 7 5825U with Radeon Graphics
CPU 核数22
内存3.3Gi3.3Gi
Swap15Gi15Gi
时区Asia/ShanghaiAsia/Shanghai
SELinuxDisabledDisabled
firewalldinactiveinactive
securecmddactiveactive

磁盘空间:

节点根分区/home分区
node170G,总用 15G,可用 56G50G,总用 1.7G,可用 49G
node270G,总用 14G,可用 57G50G,总用 1.6G,可用 49G

关键系统参数:

参数
open files65536
max user processes65536
memlock50000000 KB
kernel.sem5010 64128000 50100 1280
net.ipv4.ip_local_reserved_ports8890,54321

2.3 安装介质

文件节点路径大小SHA256
KingbaseES_V009R003C018B0003_Lin64_install.iso/install/KingbaseES_V009R003C018B0003_Lin64_install.iso1.3Ge4c04cbb1c4a1277fc5e0fdecca8e3d57d6d10e2ad247fde4fac53c670f6bcd2
license.dat/install/license.dat4.9K3cf5a2109695e59a847f012cf11849b616b631d212c192aefb76194ab2a594fe

三、读写分离集群扩容

3.1 新节点准备

项目
主机名node3
IP192.168.40.114/24
网卡ens192
网关192.168.40.2
root 密码kingbase.123
kingbase 用户已存在
数据库端口 54321未监听
securecmdd 端口 8890未监听
firewalldinactive
SELinuxDisabled

node3 当前网络:

ens192 UP192.168.40.114/24 default via192.168.40.2 dev ens192

3.2 新节点配置

3.2.1 配置主机名

hostnamectl set-hostname node3

配置hosts文件(node1与node2同时配置)

192.168.40.112 node1192.168.40.113 node2192.168.40.114 node3

关闭 firewalld

systemctl stop firewalld systemctl disable firewalld

关闭 SELinux

sed-i's/^SELINUX=.*/SELINUX=disabled/'/etc/selinux/config

准备扩容目录

mkdir-p/home/kingbase/cluster/installchown-Rkingbase:kingbase /home/kingbase/clusterchmod-R755/home/kingbase/cluster

配置 limits 参数,写入资源限制

cat>/etc/security/limits.d/99-kingbase.conf<<'EOF' kingbase soft nofile 65536 kingbase hard nofile 65536 kingbase soft nproc 65536 kingbase hard nproc 65536 kingbase soft core unlimited kingbase hard core unlimited kingbase soft memlock 50000000 kingbase hard memlock 50000000 EOF

3.2.2 配置 sysctl 参数

写入 /etc/sysctl.d/99-kingbase-ha.conf:

cat>/etc/sysctl.d/99-kingbase-ha.conf<<'EOF' kernel.sem = 5010 64128000 50100 1280 net.ipv4.ip_local_reserved_ports = 8890,54321 EOF

同时写入 /etc/sysctl.conf,避免被原配置覆盖:

sed-i'/^kernel.sem/d'/etc/sysctl.confsed-i'/^net.ipv4.ip_local_reserved_ports/d'/etc/sysctl.confcat>>/etc/sysctl.conf<<'EOF' kernel.sem = 5010 64128000 50100 1280 net.ipv4.ip_local_reserved_ports = 8890,54321 EOF

立即生效:

sysctl-wkernel.sem='5010 64128000 50100 1280'sysctl-wnet.ipv4.ip_local_reserved_ports='8890,54321'

3.2.3 配置 SSH 服务参数

优化 SSH 连接,关闭 DNS 反查和 GSSAPI:

sed-i's/^#\?UseDNS.*/UseDNS no/'/etc/ssh/sshd_configsed-i's/^#\?GSSAPIAuthentication.*/GSSAPIAuthentication no/'/etc/ssh/sshd_config systemctl reload sshd

3.2.4 生成 SSH key

root 用户:

mkdir-p/root/.sshchmod700/root/.ssh ssh-keygen-q-trsa-b3072-N''-f/root/.ssh/id_rsachmod600/root/.ssh/id_rsachmod644/root/.ssh/id_rsa.pub

kingbase 用户:

su- kingbase-c"mkdir -p ~/.ssh && chmod 700 ~/.ssh"su- kingbase-c"ssh-keygen -q -t rsa -b 3072 -N '' -f ~/.ssh/id_rsa"chmod600/home/kingbase/.ssh/id_rsachmod644/home/kingbase/.ssh/id_rsa.pubchown-Rkingbase:kingbase /home/kingbase/.ssh

3.2.5 配置 known_hosts

写入三台节点的 SSH 指纹:

foruinroot kingbase;dohome=$(["$u"=root]&&echo/root||echo/home/kingbase)touch"$home/.ssh/known_hosts"fortargetin192.168.40.112192.168.40.113192.168.40.114 node1 node2 node3;dossh-keygen-R"$target"-f"$home/.ssh/known_hosts">/dev/null2>&1||truedonessh-keyscan-H192.168.40.112192.168.40.113192.168.40.114 node1 node2 node3>>"$home/.ssh/known_hosts"2>/dev/null||truechown-R"$u:$u""$home/.ssh"chmod644"$home/.ssh/known_hosts"done

3.2.6 配置三节点 SSH 互信

将 node1、node2、node3 上 root 和 kingbase 用户的公钥统一追加到各节点:

/root/.ssh/authorized_keys /home/kingbase/.ssh/authorized_keys

node3 上最终授权文件权限:

chmod700/root/.ssh /home/kingbase/.sshchmod600/root/.ssh/authorized_keys /home/kingbase/.ssh/authorized_keyschown-Rroot:root /root/.sshchown-Rkingbase:kingbase /home/kingbase/.ssh

验证 node3 到 node1:

sshroot@node1hostnamesu- kingbase-c"ssh root@node1 hostname"su- kingbase-c"ssh kingbase@node1 hostname"

3.3 新节点扩容前准备

3.3.1 检查主节点位置

我这里主节点是node2

su- kingbase-c"/home/kingbase/cluster/install/kingbase/bin/repmgr -f /home/kingbase/cluster/install/kingbase/etc/repmgr.conf cluster show"

3.3.2 准备 node3 临时扩容目录

先在node2主节点

scp-r/home/kingbase/cluster/install/kingbase/bin\/home/kingbase/cluster/install/kingbase/lib\/home/kingbase/cluster/install/kingbase/share\root@192.168.40.114:/home/kingbase/kes_expand_stage/kingbase

3.3.3 准备扩容节点临时扩容目录

我的扩容节点是node3

exportKB_STAGE=/home/kingbase/kes_expand_stage/kingbaseexportKB_BIN=$KB_STAGE/binexportCONF=$KB_BIN/install.confexportPRIMARY_IP=192.168.40.113exportEXPAND_IP=192.168.40.114exportEXPAND_NODE_ID=3exportEXPAND_INSTALL_DIR=/home/kingbase/cluster/installexportMAX_RATE=64M##重建备库clone同步速率控制(MB/s),不限制的话设为0


集群配置

awk-vprimary_ip="$PRIMARY_IP"\-vexpand_ip="$EXPAND_IP"\-vnode_id="$EXPAND_NODE_ID"\-vinstall_dir="$EXPAND_INSTALL_DIR"\-vmax_rate="$MAX_RATE"' BEGIN { in_expand=0 } { if ($0 == "[expand]") { print "[expand]" print "expand_type=\"0\"" print "primary_ip=\"" primary_ip "\"" print "expand_ip=\"" expand_ip "\"" print "node_id=\"" node_id "\"" print "sync_type=\"\"" print "install_dir=\"" install_dir "\"" print "zip_package=\"\"" print "net_device=(ens192)" print "net_device_ip=(" expand_ip ")" print "license_file=(license.dat)" print "db_password=\"12345678ab\"" print "deploy_by_sshd=\"1\"" print "ssh_port=\"22\"" print "scmd_port=\"8890\"" print "max_rate=\"" max_rate "\"" in_expand=1 next } if (in_expand == 1 && $0 ~ /^\[/) { in_expand=0 print next } if (in_expand == 0) { print } } '"$CONF">"$CONF.tmp"&&mv-f"$CONF.tmp""$CONF"chownkingbase:kingbase"$CONF"sed-n'/^\[expand\]/,/^\[/p'"$CONF"

3.3.4 扩容前检查

hostnametest!-e/home/kingbase/cluster/install/kingbase&&echo"node3 正式安装目录干净"ss-lntp|egrep'54321|8890'||echo"node3 未监听 54321 和 8890"

3.4 开始扩容

cd/tmp/kes_expand_stage/kingbase/bin ./cluster_install.shexpand|tee/tmp/kes_expand_node3_$(date+%Y%m%d%H%M%S).log


集群节点扩容完毕

四、重建备库的克隆同步速率控制

4.1 重建前状态确认

4.1.1 集群查看状态

su- kingbase-c"/home/kingbase/cluster/install/kingbase/bin/repmgr -f /home/kingbase/cluster/install/kingbase/etc/repmgr.conf cluster show"

4.1.2 在主节点写入测试数据

先在node3设置个密码变量

exportKINGBASE_PASSWORD='12345678ab'

连接node2主库

/home/kingbase/cluster/install/kingbase/bin/ksql-h192.168.40.113-p54321-Usystem-dtemplate1

创建测试数据

create tableifnot exists ha_rebuild_rate_demo(idint primary key, note text, created_at timestamp default now());insert into ha_rebuild_rate_demo(id,note)values(1,'before rebuild node3 with clone rate limit');select* from ha_rebuild_rate_demo;

4.1.3 配置环境变量

设置变量:
使用32M限速重新clone

exportKB_HOME=/home/kingbase/cluster/install/kingbaseexportKB_BIN=$KB_HOME/binexportREPMGR_CONF=$KB_HOME/etc/repmgr.confexportDATA_DIR=$KB_HOME/dataexportPRIMARY_IP=192.168.40.113exportCLONE_RATE=32M

4.2 停止待重建备库

停止node3本地HA和数据库

停止node3本地服务:

##停止securecmd/home/kingbase/cluster/install/kingbase/bin/sys_HAscmdd.sh stopsu- kingbase##停止本地HA/home/kingbase/cluster/install/kingbase/bin/sys_monitor.sh stoplocal##停止数据库/home/kingbase/cluster/install/kingbase/bin/sys_ctl-D/home/kingbase/cluster/install/kingbase/data-mfast-wstop

确认54321已经停止

ss-lntp|grep54321||echo"node3 数据库已停止"

4.3 清理旧备库环境

4.3.1 检查复制槽

在node2上先配置一下变量

exportKINGBASE_PASSWORD='12345678ab'

连接主库:

/home/kingbase/cluster/install/kingbase/bin/ksql-h192.168.40.113-p54321-Usystem-dtemplate1

删除复制槽

selectslot_name, active from pg_replication_slots whereslot_name='repmgr_slot_3';selectpg_drop_replication_slot('repmgr_slot_3');

4.3.2 移动旧数据目录

在node3中移动旧数据目录

cd/home/kingbase/cluster/install/kingbasemvdata data.bak.rebuild.$(date+%Y%m%d%H%M%S)ls-lddata*

4.4 开始重建

设置环境变量

exportKB_HOME=/home/kingbase/cluster/install/kingbaseexportKB_BIN=$KB_HOME/binexportREPMGR_CONF=$KB_HOME/etc/repmgr.confexportDATA_DIR=$KB_HOME/dataexportPRIMARY_IP=192.168.40.113exportCLONE_RATE=32M

4.4.1 执行限速 clone(32mb/s)

$KB_BIN/repmgr-f$REPMGR_CONF-h$PRIMARY_IP-Uesrep-desrep-p54321--fast-checkpoint-D$DATA_DIRstandby clone-r$CLONE_RATE

4.4.2 启动备库

启动node3数据库

$KB_BIN/sys_ctl-w-t60-D$DATA_DIR-l$KB_HOME/logfile start

重新注册 node3 备库

$KB_BIN/repmgr-f$REPMGR_CONFstandby register-F--upstream-node-id=2

启动 repmgrd 守护进程

$KB_BIN/repmgrd-f$REPMGR_CONF--daemonize


启动本地 HA

$KB_BIN/sys_monitor.sh startlocal ha

查看集群状态

$KB_BIN/repmgr-f$REPMGR_CONFcluster show

4.5 验证备库

进库验证

selectsys_is_in_recovery();


小结

本次重建 node3 备库时,通过 repmgr standby clone -r 32M 对 clone 同步速率进行了限制。实际执行日志中可以看到底层调用:

sys_basebackup … -S repmgr_slot_3 -r 32M

其中 -r 32M 表示基础备份/克隆过程中最大传输速率限制为 32MB/s。重建完成后,重新启动 node3 数据库并执行 repmgr standby register -F --upstream-node-id=2 注册备库,最终 repmgr cluster show 显示 node3 恢复为 standby,跟随 node2,LSN_Lag 为 0 bytes。

五、主库故障下并行检测

5.1 环境准备

5.1.1 确认当前集群状态

su- kingbase-c"/home/kingbase/cluster/install/kingbase/bin/repmgr -f /home/kingbase/cluster/install/kingbase/etc/repmgr.conf cluster show"

5.1.2 打开HA日志观察窗口

node2 打开 HA 日志观察窗口

tail-n0-f$KB_HOME/log/hamgr.log$KB_HOME/log/kbha.log


node3 打开 HA 日志观察窗口

tail-n0-f$KB_HOME/log/hamgr.log$KB_HOME/log/kbha.log

5.2 故障模拟

node1 模拟主库故障

先停止 node1 本地 HA:

$KB_BIN/sys_monitor.sh stoplocal ha

然后停止 node1 主库数据库:

$KB_BIN/sys_ctl-D$DATA_DIR-mimmediate stop

观察node2与node3的日志窗口

node2:

node3:

5.3 故障恢复

5.3.1 恢复启动ha组件

$KB_BIN/sys_monitor.sh startlocal ha

进程验证

ps-ef|egrep'repmgrd|kbha|kingbase -D'|grep-vgrep

5.3.2 最终验证

$KB_BIN/repmgr-f$REPMGR_CONFcluster showipaddr show ens192|grep192.168.40.115

小结

演练前,集群状态为 node1 主库,node2、node3 为备库,并且两个备库均正常跟随 node1。随后在 node2 和 node3 分别打开 hamgr.log、kbha.log 日志窗口,用于观察主库故障后的检测过程。

在 node1 上停止本地 HA 组件并关闭数据库后,node2 和 node3 都检测到了原主库 node1 的数据库端口不可连接,日志中出现了 connection to database failed、unable to connect to node “node1” 等信息。同时,两个备库都对可信服务器192.168.40.2进行连通性检测,确认故障不是由自身网络异常引起的。

随后集群进入故障确认和升主流程。最终 node2 被提升为新的主库,虚拟 IP 192.168.40.115从 node1 漂移到 node2。node1 自动恢复为 node2 的备库,node3 也重新跟随 node2。

本次验证说明,在主库故障场景下,多个备库节点会并行检测主库状态,并结合可信服务器、复制状态和 HA 日志判断故障范围。确认主库不可用后,集群能够自动完成候选节点升主、VIP 漂移和其他节点重新跟随,保证读写分离集群具备较好的高可用切换能力。整个切换流程的时长大概在45秒左右

六、选举与升主流程优化

6.1 选举策略优化目标

当前 node2 是主库,本节目标是:当 node2 故障时,让 node3 优先升主,node1 作为次选候选节点。
也就是把优先级调整为:

node3priority=200优先升主 node1priority=50次选 node2priority=100当前主库,保持默认

6.2 检查状态

$KB_BIN/repmgr-f$REPMGR_CONFcluster show

6.3 策略配置

6.3.1 在 node1 上降低候选优先级

把 node1 的升主优先级改成 50

exportKB_HOME=/home/kingbase/cluster/install/kingbaseexportREPMGR_CONF=$KB_HOME/etc/repmgr.confifgrep-q"^priority="$REPMGR_CONF;thensed-i's/^priority=.*/priority=50/'$REPMGR_CONFelsesed-i"/^conninfo=/a priority=50"$REPMGR_CONFfichownkingbase:kingbase$REPMGR_CONFgrep-n"^priority"$REPMGR_CONF

6.3.2 重新注册 node1 的优先级

把 node1 配置文件里的新优先级同步到 repmgr 集群元数据中

$KB_BIN/repmgr-f$REPMGR_CONFstandby register-F--upstream-node-id=2

6.3.3 在 node3 上提高候选优先级

把 node3 的升主优先级改成 200,这样当主库 node2 故障时,node3 会比 node1 更优先成为升主候选节点。

exportKB_HOME=/home/kingbase/cluster/install/kingbaseexportREPMGR_CONF=$KB_HOME/etc/repmgr.confifgrep-q"^priority="$REPMGR_CONF;thensed-i's/^priority=.*/priority=200/'$REPMGR_CONFelsesed-i"/^conninfo=/a priority=200"$REPMGR_CONFfichownkingbase:kingbase$REPMGR_CONFgrep-n"^priority"$REPMGR_CONF

6.3.4 重新注册 node3 的优先级

把 node3 的 priority=200 写入集群元数据

$KB_BIN/repmgr-f$REPMGR_CONFstandby register-F--upstream-node-id=2

6.3.5 在node2验证优先级是否生效

$KB_BIN/repmgr-f$REPMGR_CONFcluster show

6.4 模拟故障测试

6.4.1 在 node3 打开日志观察窗口

tail-n0-f$KB_HOME/log/hamgr.log$KB_HOME/log/kbha.log


6.4.2 模拟 node2 主库故障

先停止 node2 本地 HA 组件:

$KB_BIN/sys_monitor.sh stoplocal ha

然后停止 node2 主库数据库:

$KB_BIN/sys_ctl-D$DATA_DIR-mimmediate stop

6.4.3 观察选举与升主日志


6.4.4 验证 node3 是否成为新主库

$KB_BIN/repmgr-f$REPMGR_CONFcluster show

再确认 VIP 是否漂移到 node3:

ipaddr show ens192|grep192.168.40.115

优化成功

小结

在优化前,node1、node2、node3 的 Priority 均为 100,多个备库在主库故障时都具备升主条件,升主结果不够直观。为了让选举结果更符合预期,本次将 node1 的优先级调整为 50,将 node3 的优先级调整为 200,使 node3 成为更优先的升主候选节点。

随后模拟当前主库 node2 故障,node1 和 node3 同时检测到 node2 的数据库连接失败,并通过可信服务器确认自身网络正常。故障确认后,集群根据调整后的优先级完成候选节点选择,最终 node3 被提升为新的主库,并成功接管虚拟 IP 192.168.40.115。

最终集群状态显示,node3 为 primary,node1 和 node2 均作为备库跟随 node3,且 LSN_Lag 为 0 bytes。这说明通过调整 priority 参数,可以影响自动故障切换时的升主候选顺序,使选举和升主流程更加可控。

总结

这次模拟了 KingbaseES 读写分离高可用集群的运维场景,完成了从集群扩容、备库重建到主库故障切换的完整实践验证。花了一周时间做测试,每天下班写一点终于肝完了~

整体来看,KingbaseES 读写分离高可用集群提供了比较完整的运维能力。从扩容到重建,从故障检测到自动切换,再到升主策略优化,都可以通过工具和参数进行管理。通过这次实践,也加深了对数据库高可用架构的理解:高可用的目标不是完全避免故障,而是在故障发生时尽快发现、准确判断、自动切换,并在切换后保持集群状态清晰可控。

http://www.jsqmd.com/news/1135415/

相关文章:

  • STM32L081CB与Si4731收音机模块开发指南
  • ClaudeCode五分钟安装教程!有手就能用上顶级AI编程助手
  • Gazebo仿真PX4+3D激光雷达的搭建
  • 分布式记忆协调_agent-memory-coordinator
  • AI中的表格怎么导出——“AI导出鸭”,深度测评来了!
  • 低成本快速搭建一个博客网站(分享记录)
  • 【单智能体】人寿保险保障顾问案例讲解(附完整源码)
  • YOLOv8可回收塑料识别分类检测系统(项目源码+YOLO数据集+模型权重+UI界面+python+深度学习+环境配置)
  • 如何在Windows上优雅处理iPhone拍摄的HEIF照片?HEIF Utility一站式解决方案
  • AI 很强,但为什么还会“忘”?看懂上下文,你就知道怎么和它合作
  • de风——【从零开始学习Linux】(三):全面总结瞧一瞧,权限管理没烦恼
  • GitHub CICD流水线_agent-ops-cicd-github
  • 豆包接入抖音生态实战指南
  • Grok 复制有星号 文档导出乱码难整理?AI 导出鸭一站式清除格式瑕疵
  • Windows 10 WSL2 安装问题排查与解决全记录
  • 抖音无水印视频下载器:3分钟学会批量保存高清内容
  • 新手友好!基于零代码平台浏览器市场与用户画像分析-数据加工(1)全流程演示
  • 27. 【C语言】编写可移植的头文件与模块
  • 【社会科学】【企业管理】【管理科学】第二十篇 售前-销售-研发-交付-财务-会计-律师-其他员工的配合模型01
  • 终极跨平台图像格式兼容解决方案:开源HEIF处理工具技术深度解析与实战指南
  • Level 4自动驾驶系统设计15——NCAP/NOA场景 2
  • REPENTOGON深度解析:解锁以撒结合模组开发的全新境界
  • Presenting Large Language Models as Companions Affects What Mental Capacities People Attribute to...
  • Centos系统学习
  • web应用技术作业7
  • 行业落地案例:白帽GEO优化赋能艺考机构全域增长|途耀传媒携手征途艺考达成战略合作
  • ChatGPT 转 Word 工具推荐?AI 导出鸭硬核转换,Mermaid / 公式全兼容
  • 顺序表,链表,复杂度相关的OJ题
  • 【关注可白嫖源码】--springboot小区物业管理系统[编号:project36977](案例分析)
  • Vision Transformer (ViT) 代码实现详解:从 Patch Embedding 到 MLP Head 的 5 个关键模块