☰
CentOS 7.x下用Docker与Shell脚本一键部署Redis Cluster集群
2026/10/13 1:09:44 网站建设 项目流程

简介:一套基于Docker的Redis集群一键部署Shell脚本,针对CentOS 7.x环境设计,面向运维工程师、后端开发及需要快速搭建Redis集群的测试人员,解决手动逐节点初始化配置繁琐、易出错的问题。压缩包共6个文件,整体大小22.46MB,包含3个Shell脚本(自动部署、辅助构建、卸载清理)、1个Redis配置模板、1个Docker镜像离线tar包和1份Markdown说明文档,脚本与配置文件分离,便于按需调整参数。该方案已有1055人学习下载,作者标明'亲测可用',具备一定实践参考价值。使用时仅需按说明传入集群相关参数,脚本会自动完成镜像加载、容器创建与集群组建;离线镜像包避免了网络拉取失败,卸载脚本可一键清理环境。README提供了清晰的参数说明与执行流程,适合CentOS 7.x服务器上快速复现和排错,也便于后续扩容与故障演练。

1. CentOS 7.x 上想用 Docker 一键拉起 Redis 集群?这套 Shell 脚本值得先拆一遍

如果你和我一样,给测试环境或小规模生产环境搭过 Redis 集群,大概率记得那些手动敲命令的深夜:三台机器、六个节点、主从关系、槽位分配,再加一个 docker run 都要带四五个参数。这套脚本就是把 CentOS 7.x 上「Docker + Redis Cluster + Shell」三者串起来的一次完整落地:自动检查环境、生成 redis.conf、用 for 循环启动节点、再调用 redis-cli 自动握手建集群。它解决的不是“能不能跑”,而是“怎么稳定地一键跑完”。适合三类人:被手动部署折磨过的运维、需要在本地复现集群环境的后端开发,以及想借真实脚本入门 shell 编程的容器学习者。下面我按拆项目的方式,把脚本的设计逻辑、用法和五个高频坑一次讲透。

2. Redis Cluster 与 Docker 部署选型:为什么是这三件套

2.1 先想清楚:哨兵模式和 Redis Cluster,脚本为什么选后者

Redis 的高可用方案常见有两套。一套是哨兵模式,负责监控主节点、自动故障转移,但数据分片还是得靠业务方自己处理;另一套就是 Redis Cluster,从 3.0 开始引入,内置 16384 个哈希槽,靠槽位把 key 分散到多个主节点上,每个主节点可以挂副本。两者最大的区别在于:哨兵模式解决的只是“主挂了怎么办”,Redis Cluster 解决的是“数据放不下、写不进去怎么办”。

这套脚本选择搭 Cluster,核心原因就是目标场景需要多写多读。六个节点组成三主三从,三个主节点分别承担一部分槽位,写入压力被分散;三个从节点各自复制主节点数据,主节点故障时从节点自动提升。如果你只是单机 Redis 加个哨兵,那根本不需要走集群这条路。反过来说,一旦决定用 Cluster,就要面对端口规划、总线端口、节点握手这些手动操作容易翻车的地方——这正是脚本存在的意义。

2.2 为什么用 Docker 而不是直接在宿主机上装 Redis

在 CentOS 7.x 上直接yum install redis也能装,但版本往往停留在 3.x,而 Redis Cluster 在 5.x 之后才算成熟,槽位迁移、集群缩扩容都有明显改进。用 Docker 的好处一是版本可控,镜像指定 redis:7.0.15 就用 7.0.15,不会出现 yum 源升级后 Redis 小版本跳动导致集群行为不一致的问题;二是环境隔离,redis.conf、数据目录、日志全部挂在宿主机的 /opt/redis-cluster 下,想清理环境直接docker rm再删目录,不留残留。

还有一个实际好处是故障恢复。手动部署的 Redis 进程如果崩了,systemd 不一定帮你拉起来;而容器可以设置--restart unless-stopped,宿主机重启后 Docker 服务一启动,容器自动跟着起来,集群恢复的成本低很多。对运维来说,这种“重启后不用人工干预”的能力比什么都实在。

2.3 host 网络还是 bridge 网络:脚本为什么选 host

这是拆这套脚本时最需要理解的一个选型。Docker 默认的 bridge 网络会把容器隔离在一个内部网段里,容器之间通过网桥互通。但如果 Redis Cluster 跨了三台宿主机,bridge 模式下要么做端口映射,要么配置 docker 的 overlay 网络,前者在遇到 Cluster 总线端口时特别容易漏映射,后者需要额外的 key-value 存储和网络初始化,复杂度直接上一截。

对比下来,host 网络模式是最省事的选择:容器直接复用宿主机网络栈,监听端口就是宿主机端口,不需要 -p 映射,也不需要配置跨主机网络。Redis Cluster 的节点之间除了业务端口 6379/6380,还会用“业务端口 + 10000”的端口做集群总线通信,比如 6379 对应 16379。host 模式下这个总线端口天然可达,配合防火墙放行端口段即可。

对比项bridge 模式host 模式(脚本选用)
端口映射每个容器都要配置 -p无需映射,监听即宿主机端口
跨主机通信需要 overlay 网络或手动路由天然互通,走宿主机网络
集群总线端口容易漏映射导致节点握手失败自动可达,只需放行防火墙
适用场景单机多容器、端口需要隔离跨主机 Redis Cluster 部署

脚本放弃 docker-compose 也是出于同样的务实考虑。CentOS 7.x 的默认 yum 源里 docker-compose 版本往往偏老,装完可能遇到 Python 依赖问题;而一个纯 Shell 脚本零额外依赖,只要宿主机有 docker 和 redis-cli 就能跑。对想理解部署逻辑的人来说,脚本里的 for 循环和参数处理比 compose 文件更能看清每一步在做什么。

3. 一键脚本的核心逻辑:从环境检查到集群锁定

3.1 脚本的整体结构与配置变量

拆这套脚本,先从头部配置入手。脚本把所有需要按机器实际情况改的参数集中在开头一段,而不是散落在函数里。我用注释把关键参数标一下:

#!/bin/bash # redis-cluster-deploy.sh # 适用环境:CentOS 7.x / Docker / 三台宿主机 # 用法:bash redis-cluster-deploy.sh set -euo pipefail # ===== 按你的实际环境修改 ===== MASTER_HOSTS=(192.168.1.10 192.168.1.11 192.168.1.12) # 宿主机 IP 列表 NODE_PER_HOST=2 # 每台宿主机跑几个 redis 节点 START_PORT=6379 # 起始 redis 端口,每台机器递增 REPLICAS=1 # 每个主节点挂几个从节点 REDIS_IMAGE=redis:7.0.15 # 镜像版本,建议固定 tag REDIS_BASE_DIR=/opt/redis-cluster # 配置与数据挂载根目录 CLUSTER_NET=redis-cluster-net # 自定义 docker 网络名

这段配置看着简单,但每个变量都直接影响集群拓扑。MASTER_HOSTS这个数组决定了集群分布在哪些机器上,脚本后续的 for 循环就是遍历它;NODE_PER_HOST为 2 时,三台机器共产生六个节点,正好组成三主三从;START_PORT是从 6379 开始递增,每台机器上的两个节点分别用 6379 和 6380。REPLICAS=1表示每个主节点挂一个从节点,最终三个主、三个从。REDIS_IMAGE必须固定具体版本号,不要用redis:latest,否则哪天镜像更新了,集群里的节点版本不一致,槽位迁移时可能出现意想不到的行为。

set -euo pipefail这一行是脚本稳定性的关键:-e让脚本在任意命令失败时立即退出,-u防止未定义变量导致静默错误,pipefail让管道中第一个失败的命令被视为整个管道失败。对部署脚本来说,尽早失败比带着错误配置继续跑完更友好。

3.2 环境检查与公共配置生成

脚本进入正题前会做一轮环境检查,这一步往往被手动部署的人忽略,但恰恰是集群建不起来的常见原因。逻辑上分三块:检查 docker 命令是否存在、检查 redis-cli 是否可用、创建统一的配置目录。

# 1. 检查基础命令 command -v docker >/dev/null 2>&1 || { echo "docker 未安装或不在 PATH 中"; exit 1; } command -v redis-cli >/dev/null 2>&1 || { echo "redis-cli 未安装,请先安装 redis-tools"; exit 1; } # 2. 检查 docker 服务是否在运行 if ! docker info >/dev/null 2>&1; then echo "docker 服务未运行,尝试启动..." systemctl start docker systemctl enable docker fi # 3. 创建统一挂载目录,避免权限混乱 mkdir -p ${REDIS_BASE_DIR}/{data,conf}

这里用command -v而不是which,是因为which在部分 CentOS 7.x 最小安装里可能不存在,而command -v是 Shell 内建命令,更稳妥。docker info判断服务是否可用比systemctl status docker更直接,因为即使服务起来了,Docker 守护进程也可能因为权限或内核问题无法响应。

目录规划上,data和conf分开挂在宿主机,是为了后续备份和排查方便。如果所有文件堆在一个目录里,时间长了你自己都分不清哪个文件属于哪个容器。

3.3 节点启动与自动集群握手

节点启动是整个脚本的核心,它用双层 for 循环遍历「宿主机 IP × 节点序号」,对每个组合生成独立端口和独立 redis.conf,然后启动容器。这里直接体现 shell 脚本 for 循环在批量操作上的优势:

# 为每台机器上的每个节点生成配置并启动容器 INDEX=0 for HOST_IP in "${MASTER_HOSTS[@]}"; do for SLOT in $(seq 1 ${NODE_PER_HOST}); do PORT=$((START_PORT + SLOT - 1)) # 生成独立 redis.conf cat > ${REDIS_BASE_DIR}/conf/redis-${PORT}.conf <<EOF port ${PORT} cluster-enabled yes cluster-config-file nodes-${PORT}.conf cluster-node-timeout 5000 appendonly yes appendfsync everysec daemonize no protected-mode no bind 0.0.0.0 dir /data logfile "" EOF # 启动容器:host 网络 + 统一挂载 docker run -d --name redis-${HOST_IP}-${PORT} \ --network host \ --restart unless-stopped \ -v ${REDIS_BASE_DIR}/conf/redis-${PORT}.conf:/etc/redis/redis.conf:ro \ -v ${REDIS_BASE_DIR}/data/redis-${PORT}:/data \ ${REDIS_IMAGE} \ redis-server /etc/redis/redis.conf # 组装节点地址列表 NODE_LIST="${NODE_LIST} ${HOST_IP}:${PORT}" done done

这段有几个参数必须说清楚。cluster-enabled yes是节点进入集群模式的开关,不开启的话 redis-cli --cluster create 会直接拒绝这个节点;cluster-config-file指定节点保存集群状态的文件名,每个节点必须独立,否则多个容器共享同一个 nodes.conf 会互相覆盖;daemonize no是因为容器里 redis 必须以前台进程运行,否则 Docker 会认为容器没事干就把它退出;bind 0.0.0.0配合protected-mode no是跨主机访问的前提,如果 bind 只写 127.0.0.1,其他机器上的节点握手永远不可能成功。

--network host这个参数前面已经解释过,这里补充一点:host 模式下端口是直接占用的,脚本里PORT=$((START_PORT + SLOT - 1))的计算必须保证同一台机器上的端口不冲突。比如 NODE_PER_HOST 为 2 时,第一台机器用 6379 和 6380,第二台、第三台同样复用这两个端口——因为 host 网络下端口是绑在各自宿主机上的,不同机器之间可以安全复用。

容器启动完后脚本还不能马上建集群。Redis 节点从启动到进入可握手状态需要几秒钟,直接执行 cluster create 大概率遇到连接拒绝。脚本这里会做一个轮询等待,循环执行redis-cli -p PORT ping,直到所有节点都返回 PONG:

# 等待所有节点进入就绪状态 for NODE in ${NODE_LIST}; do IP_PORT=(${NODE//:/ }) IP=${IP_PORT[0]} PORT=${IP_PORT[1]} for TRY in {1..30}; do if redis-cli -h ${IP} -p ${PORT} ping >/dev/null 2>&1; then break fi sleep 2 if [ ${TRY} -eq 30 ]; then echo "节点 ${NODE} 30 秒内未就绪,请检查容器日志" exit 1 fi done done

等待逻辑里的 30 次重试、每次间隔 2 秒,是最多 60 秒的容忍窗口。如果 60 秒后节点还 ping 不通,脚本直接退出,同时提示查看容器日志,避免后续 cluster create 卡在令人费解的 waiting 状态。这里的IP_PORT=(${NODE//:/ })是 Shell 字符串替换加上数组拆分的写法,把 "192.168.1.10:6379" 拆成 IP 和端口两个独立变量。

最后一步是组建集群。脚本优先使用redis-cli --cluster create,因为它会帮我们处理节点握手、槽位分配和副本绑定,比手动CLUSTER MEET安全得多:

# 组建集群:自动分配槽位并绑定副本 echo "开始创建集群..." redis-cli --cluster create ${NODE_LIST} \ --cluster-replicas ${REPLICAS} \ --cluster-yes # 输出集群状态 redis-cli -h ${MASTER_HOSTS[0]} -p ${START_PORT} cluster info | head -10

--cluster-replicas 1的意思是每个主节点自动挂一个从节点,脚本会按照节点列表顺序尽量把主从分布在不同宿主机上,避免同一台机器既是主又是它的副本。--cluster-yes跳过交互确认,否则 cluster create 会停下来问你 "Can I set the above configuration?",一键部署就成了半自动。集群创建后,cluster info的前几行会显示cluster_state:ok和槽位分配情况,一眼就能判断建集群是否成功。

4. 部署实操:CentOS 7.x 上把几个变量换成你的 IP 就能跑

4.1 部署前准备:镜像、防火墙、内核参数一个都别漏

拿到脚本别急着跑,先把宿主机环境过一遍。CentOS 7.x 上我一般会先确认 Docker 版本能正常启动,然后处理三个高概率拦路的地方:防火墙、SELinux、内核内存参数。

第一步安装并启动 Docker(如果已经装好可以跳过):

# 安装 Docker(CentOS 7.x 常见做法) yum install -y yum-utils device-mapper-persistent-data lvm2 yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo yum install -y docker-ce systemctl start docker systemctl enable docker # 拉取 Redis 镜像,固定版本号 docker pull redis:7.0.15

systemctl enable docker这步很容易被忽略。不加的话宿主机重启后 Docker 服务不会自动启动,容器全部处于 exited 状态,集群直接瘫痪。镜像下载这一步单独执行还有个好处:部署时脚本不会因为网络问题卡在拉镜像阶段,节省排错时间。

然后是防火墙。host 网络模式下,Redis 的业务端口和 Cluster 总线端口都直接暴露在宿主机网络上,firewalld 如果不放行,节点之间握手会失败。常见做法是放行固定端口段,而不是直接关防火墙:

# 放行 Redis 业务端口和 cluster bus 端口(6379-6380 和 16379-16380) firewall-cmd --permanent --add-port=6379-6380/tcp firewall-cmd --permanent --add-port=16379-16380/tcp firewall-cmd --reload # 确认放行结果 firewall-cmd --list-ports

这里特别强调 Cluster 总线端口(业务端口 + 10000)。很多人只放行了 6379/6380,结果集群创建时节点之间能连上业务端口,但总线端口不通,日志里反复出现 "Waiting for the cluster to join",这个问题非常难排查,因为表面看端口没毛病。至于 SELinux,如果之前没改过策略,最简单的做法是保持默认并确认 Docker 工作正常;如果遇到了诡异的权限问题,可以检查/var/log/audit/audit.log再决定。

内核参数vm.overcommit_memory是 Redis 在 fork 子进程做持久化时的内存分配策略。默认值 0 在内存压力稍大时可能导致 fork 失败,建议写入 sysctl 配置:

# 设置内存分配策略并使其持久化 echo "vm.overcommit_memory = 1" >> /etc/sysctl.conf sysctl -p

4.2 执行脚本并理解每一段输出

环境准备完就正式执行。脚本输出的每一段都要能看懂,这样失败时能快速定位在哪一步:

# 给脚本加执行权限并运行 chmod +x redis-cluster-deploy.sh bash redis-cluster-deploy.sh

正常执行时会依次看到:环境检查通过、六个容器逐个启动(每启动一个输出一行的容器 ID)、等待节点就绪期间没有报错,然后看到>>> Performing hash slots allocation on 6 nodes...这样的创建日志,最后 cluster info 输出cluster_state:ok。

看到cluster_state:ok不代表全流程完事了,我一般会等几秒再手动执行一次redis-cli --cluster check,这能确认槽位分配和副本关系都符合预期。脚本把cluster info的输出打印出来,就是这个目的——把验证步骤内置到部署里,而不是部署完再手工敲验证命令。特别要留意的输出是cluster_state:fail,这说明槽位没分配完整或者主节点之间失去联络,需要结合后面的避坑章节逐条排查。

4.3 脚本重复执行的幂等设计

一键脚本最怕跑第二次的时候把已有集群搞乱。常见做法是在脚本里加三重幂等保护:文件锁防止并发执行、容器存在性检查避免重复创建、集群状态检查避免对已存在的集群二次初始化。

# 第一重:文件锁,防止脚本并发执行 exec 9>/tmp/redis-cluster-deploy.lock if ! flock -n 9; then echo "另一个部署脚本正在运行,请稍后再试" exit 1 fi # 第二重:检查是否已有 redis 容器存在 if docker ps -a --format '{{.Names}}' | grep -q "^redis-"; then echo "检测到已有 redis 容器,跳过容器创建步骤" SKIP_CREATE=1 fi # 第三重:检查是否已是集群状态 if redis-cli -h ${MASTER_HOSTS[0]} -p ${START_PORT} cluster info 2>/dev/null | grep -q "cluster_state:ok"; then echo "集群已存在,跳过 cluster create 步骤" SKIP_CLUSTER_CREATE=1 fi

flock -n的意思是拿锁失败就立即退出而不是等待,这样能防止两个运维同事同时在两台终端上执行脚本。容器存在性检查通过docker ps -a检索名字前缀,有容器就跳过创建,避免重名冲突导致 Docker 报错。集群状态检查用实际命令验证而不是简单看容器是否运行——容器在跑但集群没建成功的情况并不少见,这时候应该补救而不是傻等。

有了这三重保护,脚本可以安全地重复执行。以前手动部署时最怕“跑一半失败了,重跑要先把旧容器删干净”,现在脚本自己判断哪些步骤要跳过、哪些要补做,容错性完全不一样。

5. 避坑排查:五条拿掉之后集群才真正稳下来

5.1 现象一:cluster create 一直停在 waiting for the cluster to join

这是我见过最多的问题。六个容器都起来了,redis-cli ping 也都通,但redis-cli --cluster create卡在>>> Waiting for the cluster to join超过 30 秒,最后超时失败。

根本原因是 Redis Cluster 节点之间除了业务端口,还要通过总线端口(业务端口 + 10000)交换 PING/PONG 消息。CentOS 7.x 的 firewalld 默认只放行了 6379 端口,16379/16380 被静默拦截,节点互相收不到总线消息,自然永远等不到集群握手成功。

解决方法是先把防火墙放行端口段:firewall-cmd --permanent --add-port=6379-6380/tcp --add-port=16379-16380/tcp,然后 reload。如果用的是云主机安全组,还要去控制台放行对应端口范围。放行后再跑一次 cluster create,通常几秒内就能完成槽位分配。

5.2 现象二:宿主机重启后容器全起来了,但集群节点状态变成 fail

现象是重启后docker ps看到所有容器都在运行,但cluster info显示cluster_state:fail,cluster nodes里每个节点都标记为 fail。

原因一般有两个。一是容器没有设置--restart unless-stopped,重启后部分容器没自动拉起;二是 redis 容器虽然起来了,但持久化数据目录里保留了旧的 nodes.conf,节点重启后拿着旧集群状态去和自己已经变化的总线端口通信。第二个原因更容易被忽略。

解决方法是先保证容器带重启策略:脚本里的--restart unless-stopped不能删,这是宿主机重启后容器能自动归位的底线。然后清理持久化数据里的旧节点信息,把cluster-config-file指向的nodes-*.conf文件删掉,再重启容器,让节点以干净状态重新握手。

5.3 现象三:docker ps 全正常,但 redis-cli -h 宿主机IP -p 6379 连不上

部署完在宿主机上执行redis-cli -h 127.0.0.1 -p 6379 ping能通,换成其他机器的 IP 就连不上,或者业务代码里通过容器 IP 访问报连接超时。

原因是 redis.conf 里bind配置成了 127.0.0.1,或者protected-mode没关闭。bind 决定了 Redis 监听在哪个网络接口上,只写本地回环地址的话,其他机器的请求根本到不了 Redis 进程;protected-mode 开启时,如果 Redis 没有密码且 bind 的不是本机地址,也会拒绝连接。

解决方法是把 redis.conf 中的bind改为0.0.0.0,同时设置protected-mode no。脚本里生成的配置默认就是这两项,如果你是自己手写 redis.conf,特别容易漏掉。改完配置后要重启对应容器,而不是只 reload 配置。

5.4 现象四:docker 命令显示系统找不到 docker 服务

在 CentOS 7.x 最小化安装环境上执行systemctl start docker提示Unit docker.service not found。

原因是没安装 Docker 或者装的是 docker-io 老版本。CentOS 7.x 的默认源里不带 docker-ce,需要先配置 Docker 官方或阿里云镜像源,再安装 docker-ce 和配套组件。这个坑多发于刚拿到一台新采购的服务器、以为系统自带 Docker 的情况。

解决方法在 4.1 节已经覆盖:使用yum-config-manager添加 docker-ce 的 yum 源,然后yum install -y docker-ce。装完记得systemctl enable docker,否则下次重启又要手动拉起。

5.5 现象五:脚本跑第二遍,节点全部变成孤立的单点

第一遍部署成功,后来因为环境调整,把脚本再跑一遍,结果所有容器都是新建的,集群状态反而没了,节点各自为政。

原因是脚本第二遍跳过了容器创建和 cluster create,但清理逻辑没做完整,或者持久化目录里残留了一堆 old nodes.conf,新旧节点文件互相干扰,集群状态无法正确恢复。

解决方法是脚本里补充一个显式的清理函数,用环境变量控制执行——比如CLEAN=1 bash redis-cluster-deploy.sh时,先删除所有 redis- 前缀容器和整个/opt/redis-cluster配置目录,再从零开始部署。我在实际工作中踩过一次后,就把清理逻辑单独拆成一个函数,绝不让“重跑脚本”这个动作模糊不清。重跑前先想清楚:是补数据,还是从零开始,两者处理方式完全不同。

6. 验证是最后一公里:cluster 状态、扩容与备份习惯

6.1 用 redis-cli 做三层健康检查

集群建完不是终点,我习惯做三层验证。第一层看cluster info的cluster_state是否为 ok,同时确认cluster_slots_assigned等于 16384;第二层看cluster nodes的每个节点角色和连接状态,确认三个主节点、三个从节点,且没有节点被标记为 fail;第三层是实际写入和读取验证,写入一个 key 到集群,看它是否被均匀分不到不同节点。

# 第三层验证:简单写入与读取 redis-cli -h 192.168.1.10 -p 6379 -c set deploy-check:001 hello redis-cli -h 192.168.1.11 -p 6379 -c get deploy-check:001

-c参数是集群模式的关键,它让 redis-cli 自动跟随槽位重定向。如果没有加-c,访问不在当前节点负责的槽位时会报MOVED错误,新手经常被这个误导以为集群有问题。

6.2 扩容方向:先 add-node 再 reshard

脚本解决的是“从零建集群”,集群建好后的扩容是另一个话题。真要加一台机器时,主流做法是先启动新节点容器,然后用redis-cli --cluster add-node把它加入集群,最后reshard迁移槽位。这个方向比改脚本重跑更安全,因为不会触动已有节点的数据。如果你希望脚本也支持扩容,可以在现有框架上扩展:把新机器 IP 追加进MASTER_HOSTS数组,然后单独写一个 add-node 的步骤,注意这一步必须手动确认槽位迁移策略,不要全自动一把梭。

6.3 备份习惯与最终建议

Redis Cluster 的持久化文件不能直接拍脑袋复制,因为 RDB 和 AOF 文件可能与集群状态不一致。我一般会在每个宿主机上对/opt/redis-cluster/data目录做定时快照,且备份前先CLUSTER SETSLOT进入维护模式,再执行BGSAVE保证数据一致。这个习惯救过我一次:测试环境集群数据全丢了,靠快照恢复后,才发现备份脚本里少了维护模式这一步。

从那以后,我每次用这类一键部署脚本,都会强制自己先跑一遍环境检查,确认防火墙端口段、SELinux 状态和内核 overcommit 参数,再执行脚本;重跑前也会刻意想清楚会不会伤害已有数据。这套脚本最大的价值不是省去几分钟的手动操作,而是把容易犯错的部署路径压缩成一条稳定可重放的路,希望你也能从中拿走自己用得上的部分。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询