我们接触到的离线部署需求,大多数都写在工单里,最简单的一句话就是“服务器连不了外网,帮我把redis装上”。因为工作环境的限制,我陆续在Linux服务器上做了多次离线安装redis的操作,从redis-6.x一路装到redis-7.4.0,踩过的坑基本都集中在“源码编译依赖”“配置参数”和“启动方式”这三块。这篇内容就围绕Linux服务器离线安装redis-7.4.0,讲讲完整流程、关键参数和我在实际操作中攒下来的经验,适合Linux运维、实施工程师,以及在无外网环境下做技术预研的朋友参考。先把结论放前面:整个过程不复杂,但准备工作决定安装速度,细节配置决定后续维护成本。
1. 为什么离线场景里,我坚持用源码编译装redis?
很多朋友第一反应是“离线安装还不简单?把别人机器上的redis目录拖过来,解压就能用”。这个思路在部分场景下能跑通,但不建议作为标准方案,原因有三个:一是二进制文件对glibc版本、CPU指令集和操作系统发行版很敏感,换到不同内核的服务器上经常出现段错误;二是二进制包内部的编译参数不可控,比如说是否带TLS、是否开启systemd支持,这些在后面配置时都会变成不确定因素;三是离线环境一旦出问题,排查手段比在线环境少很多,拿源码包重新编译,等于把主动权握在自己手里。
源码编译看起来多花了几分钟,实际上换来的是对运行环境的完全掌控。Redis官方发布的release版本基本都是tar.gz源码包,编译过程对Linux系统只有一个硬性依赖:必须要有gcc编译器和make工具。7.4.0这个版本在编译时会默认尝试链接libc的malloc实现,同时也附带了对jemalloc的支持,在安装前把gcc、make、openssl相关的库准备好,基本就是半个小时的活。如果你所在的内网环境连这些基础开发工具也没有,那准备rpm包或deb包这一步就要提前做。
再说说“离线”到底离到什么程度。我遇到的情况分两种:一种是服务器完全在内网,访问不了任何外网站点,但内部有软件源镜像或共享存储;另一种是只有一台跳板机能上网,目标服务器只能通过跳板机转发文件。这两种场景的操作思路完全相同:所有安装依赖和redis-7.4.0源码包,都要在能联网的机器上提前下载好,再传输到目标服务器。文章里所有提到的wget、yum、apt命令,都是在开发机上执行,真正到目标服务器上时,全程不联网。
选择redis-7.4.0还有一个现实原因:7.x系列已经包含了Redis在性能、安全、集群运维上的绝大多数改进,比如多线程异步删除、更完善的ACL权限控制、Redis Functions等新特性。对大部分业务来说,7.4.0比6.2系列更合适,也比8.x的尝鲜版本更稳。既然要离线安装一次,就尽量选一个在生命周期内的稳定版本,免得装完没多久又要升级。
2. 离线开工前的准备:安装包、架构确认和编译依赖
2.1 下载redis-7.4.0源码包并校验完整性
源码包的获取位置很固定,就是Redis官方的下载站点download.redis.io,也可以从GitHub的redis/redis仓库拿到带release标记的tag包。对我来说,官方download站点的地址最简单:https://download.redis.io/releases/redis-7.4.0.tar.gz。注意不要从第三方博客、未知网盘上顺手download,离线环境的软件来源必须可靠,这也方便你后续写安装交付文档时说明溯源路径。
下载完成后,先做两件事:第一是比对压缩包的大小,第二是校验SHA-256哈希值。Redis官方每个release包旁边都有一个对应的sha256文件或者哈希值记录,下载完用sha256sum redis-7.4.0.tar.gz算一下,再和官方给出的值核对。这个步骤在在线环境里显得冗余,但在离线环境里是必须的,因为文件只要经过多次传输、拷贝,就存在损坏的可能,哈希校验能保证你拿到的是原始完整的源码包。
另外我建议把source包、rpm依赖包、部署脚本放到同一个目录里,统一做成一个redis-offline-package,再一起传到服务器上。目录结构可以是这样:
redis-offline-package/ ├── redis-7.4.0.tar.gz ├── sha256.txt └── deps/ ├── 如果缺gcc,则放gcc相关rpm └── openssl-devel相关rpm这个习惯帮了我很多次。离线环境里最怕的不是安装失败,而是明明少一个依赖,却不知道少什么,在服务器上干着急。把所有材料准备齐,执行起来才有底气。
2.2 先确认系统架构和发行版,再谈安装路径
拿到源码包后,别急着解压。第一步是确认目标服务器的架构,用一条命令就能搞定:uname -m。返回x86_64就是常见的Intel/AMD 64位架构,返回aarch64就是ARM 64位架构。源代码编译虽然能自适应架构,但如果你在准备依赖包,比如gcc、openssl-devel,这些必须和系统架构匹配,不能把x86_64的rpm包塞到aarch64系统上,装的时候会直接报错。
同时要看一眼操作系统发行版信息,建议执行cat /etc/os-release。不同发行版的包管理方式不同,CentOS/RHEL系用rpm和yum,Debian/Ubuntu系用deb和apt。就算都叫Linux,glibc版本也不一样,尤其要关注一个潜在问题:如果目标服务器的glibc版本过低,而你在开发机上用太高版本的gcc编译出来的二进制,拿过去是跑不起来的。所以编译这步,我建议直接在目标服务器上完成,而不是“开发机编译好、再拷二进制”,这才是离线安装最稳妥的路径。
规划安装路径也要在准备阶段想清楚。我常用的目录方案是:
/opt/redis-7.4.0 # 主程序目录 /opt/redis-7.4.0/bin # 可执行文件 /opt/redis-7.4.0/conf # 配置文件 /opt/redis-7.4.0/data # RDB/AOF持久化数据 /opt/redis-7.4.0/logs # 日志目录有人习惯装到/usr/local/redis,也有人直接放到/etc和/var/lib。我的经验是:首次规划时把数据目录、日志目录和程序目录分开,后面做备份、扩容、迁移能省很多事。这个习惯特别适用于离线环境,一旦出问题,日志目录和数据目录独立,定位问题更快。
2.3 检查gcc和make是否满足编译要求
在正式编译前,先快速检查编译工具链。依次执行:
gcc --version make --version如果系统报command not found,说明需要先安装gcc和make。在线环境直接yum install -y gcc make或者apt install -y gcc make就完了,但离线环境就得先准备好对应系统的rpm/deb包。这里有几个操作细节需要注意:
- CentOS/RHEL系统,如果手头有完整镜像光盘,可以直接配置本地yum源,挂载光盘后
yum install -y gcc make,这是最省力气的离线安装依赖方式。 - 没有光盘镜像时,需要在有外网的机器上,用相同系统版本执行
yumdownloader --resolve把需要的rpm包全部拉下来,再传到目标服务器逐一手动安装。 - Debian/Ubuntu系统,可以用
apt download或apt-get download先把deb包下载到本地,再传到内网执行dpkg -i *.deb。
除了gcc和make,redis-7.4.0编译时如果开启TLS支持,还需要OpenSSL的开发头文件。CentOS的包名是openssl-devel,Debian系是libssl-dev。如果不需要在redis连接层做TLS加密,编译时可以显式关闭TLS来降低依赖,我后面会讲到方法。检查OpenSSL头文件是否存在,可以执行ls /usr/include/openssl/ssl.h,没有就说明缺开发包。
3. 亲手编译安装redis-7.4.0:完整命令与现场解读
3.1 解压源码包,并对make相关的几个细节上心
先把安装包拷贝到目标服务器,建议放在/opt或/home/ops这类合适的工作目录下。然后执行解压:
cd /opt tar -zxvf redis-7.4.0.tar.gz cd redis-7.4.0解压完成后先看看目录里的文件,重点看README.md和Makefile,不要跳过这一步。Redis的Makefile写得比较清晰,里面预设了很多编译选项,比如BUILD_TLS、MALLOC等。你不一定要看懂每一行,但至少要知道有哪些开关可以控制编译行为,这样遇到问题才有调整方向。
有一点需要特别提醒:有些Linux发行版默认的make不是GNU make,或者make版本太老,编译Redis时会出现莫名其妙的问题。如果发现make命令行为异常,可以用make --version确认,必要时安装或升级make。redis-7.4.0对编译工具链的要求不算激进,但基础工具过旧一定会出问题,尤其在编码阶段会报一些语法错误,实际上不是源码的问题。
编译前,我还习惯先执行一下make clean(如果之前编过的话),确保目录状态干净。如果是从第三方渠道拿到的tar包,编译前最好用strings或者file命令看看是不是纯源码,防止拿到带二进制后门的伪包。这个习惯在离线环境尤其重要,因为软件来源相对单一,安全性要自己把关。
3.2 make和make install命令的完整执行
进入源码目录后,直接执行编译:
make -j 4-j 4的意思是同时用4个任务并行编译,数字可以按服务器CPU核数调整。如果你不确定核数,直接执行nproc看一下。并行编译能显著减少等待时间,四核机器编译redis通常两三分钟就能结束,如果是老一点的服务器CPU核数少,就把-j后面的数字调小,否则IO和内存压力过大,反而拖慢速度。
编译过程中,控制台会滚动输出一堆cc编译日志,看到Hint: It's a good idea to run 'make test' ;-)说明编译已经通过。这里要提一个很多新手都忽略的点:编译通过后,不要急着做下一步,可以先运行一下make test,它在离线环境下也能执行,用来验证当前系统里编译出来的Redis二进制是否正常。测试时间会长一点,但能提前暴露大部分运行期问题。“编译能过”和“运行没问题”是两回事。
安装到指定目录,用下面的命令:
make PREFIX=/opt/redis-7.4.0 install注意PREFIX参数必须是大写,它决定redis-server、redis-cli等可执行文件的安装路径。执行完毕后,/opt/redis-7.4.0/bin目录下会出现redis-server、redis-cli、redis-benchmark、redis-check-aof、redis-check-rdb、redis-sentinel等一堆文件。看到这些文件,说明安装这一步成功了。
3.3 配置PATH,并验证redis命令可用
二进制安装完成后,可以先不配systemd,手动启动一个临时实例验证一下。执行:
export PATH=/opt/redis-7.4.0/bin:$PATH redis-server --version如果输出Redis server v=7.4.0 ...,说明命令已经可用。但要注意,这个export只在当前会话生效,重启终端就没了。要让PATH永久生效,我习惯在/etc/profile.d/下新建一个redis.sh文件,写入:
export PATH=/opt/redis-7.4.0/bin:$PATH然后执行source /etc/profile.d/redis.sh。这样下次登录自动就能敲redis-cli,不需要每次写全路径。这条看起来是小事,但在离线环境里,操作人员经常换账户、换终端,PATH配置统一了,巡检命令写起来才顺手。
临时验证一下能否正常启动,前台模式跑几秒钟:
redis-server看到启动日志没有报错,按Ctrl+C停掉。这个临时启动不写任何配置,用默认参数,用来确认二进制本身没问题。确认通过,就可以进入正式的配置和随系统启动环节。
4. 从配置到开机自启:让redis变成一台稳定的基础服务
4.1 redis.conf中建议优先调整的几个参数
Redis源码目录中自带一份redis.conf,安装时可把它复制到配置文件目录:
mkdir -p /opt/redis-7.4.0/conf cp /opt/redis-7.4.0/redis.conf /opt/redis-7.4.0/conf/redis.conf这份默认配置有几百行,大部分保持默认就行,但在正式投入前,我建议按下面的表优先调整几个参数:
| 参数 | 建议值 | 调整理由 |
|---|---|---|
| bind | 服务器的内网IP,或0.0.0.0(按需) | 默认只监听127.0.0.1,只允许本机访问,外部服务连不上 |
| port | 6379 | 默认端口,如无冲突可以不动 |
| daemonize | yes | 是否后台运行,配合systemd时可以用no,我习惯用yes,启动逻辑更简单 |
| protected-mode | no或保持yes并配密码 | 默认保护模式会在没有密码时拒绝远程访问,容易造成“连不上”错觉 |
| requirepass | 自定义强密码 | 开启认证,防止未授权访问 |
| logfile | /opt/redis-7.4.0/logs/redis.log | 统一日志路径,便于排查 |
| dir | /opt/redis-7.4.0/data | 持久化文件目录,决定dump.rdb的位置 |
| appendonly | yes | 开启AOF持久化,降低故障时丢数据的风险 |
bind参数要结合业务规划来看。同一个内网里,如果只有某个网段的业务需要访问redis,那就把bind直接写成服务器内网IP,比如bind 192.168.10.20,这样更安全。如果多套环境共用同一台服务器,需要别的机器通过虚拟IP访问,再放开。经常有人一上来就写0.0.0.0,结果redis暴露在公网机器上被扫描爆破,这在离线环境可能不明显,但在有互联网出口的机器上是高危操作。
requirepass这行,默认是注释着的。我见过不少部署人员嫌麻烦不配,在内网里觉得没事。实际上内网也不一定安全,而且只要加一行requirepass 你的密码,后续排查问题时还能减少误操作。配置密码后,redis-cli连接时要用redis-cli -a 密码或者AUTH命令认证,这里也提醒大家小心shell历史记录里泄露密码。
4.2 用systemd把redis做成开机自启服务
离线安装最常见的坑是“装上能跑,重启就没了”。手动启动redis只会让它在当前进程里运行,服务器一重启,进程就没了。要让redis作为系统服务稳定跑起来,推荐用systemd管理。在/etc/systemd/system/redis.service里新建一个Unit文件,内容大致如下:
[Unit] Description=Redis 7.4.0 Server After=network.target [Service] Type=forking ExecStart=/opt/redis-7.4.0/bin/redis-server /opt/redis-7.4.0/conf/redis.conf ExecStop=/opt/redis-7.4.0/bin/redis-cli -a 你的密码 shutdown Restart=always RestartSec=5 PIDFile=/var/run/redis_6379.pid [Install] WantedBy=multi-user.target要注意几个细节:Type=forking对应daemonize yes;ExecStop里带密码,记得把-a的密码写对,否则shutdown会认证失败;系统如果开启了SELinux,Unit文件的路径、PIDFile的目录都要有相应权限,否则service起不来。写完文件后执行:
systemctl daemon-reload systemctl enable redis systemctl start redis systemctl status redisstatus能看到当前运行状态,最前面是Active: active (running)就说明daemon已经跑起来。再用redis-cli -a 你的密码 ping测试,返回PONG就大功告成。
如果觉得Type=forking方式容易因为PID文件位置问题启动失败,也可以改一版更简单的。把daemonize改成no,Unit文件里写成Type=simple,ExecStart直接执行redis-server,不加&。我实际部署中发现,很多发行版用Type=simple更省心,因为它不依赖PID文件,systemd直接跟踪主进程,重启逻辑更清晰。这个修改只是换启动方式,不影响redis自身功能。
4.3 日志、数据目录和权限,顺手一起规划好
离线环境下,我强烈建议创建专用的运行用户,而不是用root启动redis。创建用户和目录授权,可以这样操作:
useradd -r -s /sbin/nologin redis mkdir -p /opt/redis-7.4.0/data mkdir -p /opt/redis-7.4.0/logs chown -R redis:redis /opt/redis-7.4.0然后修改redis.conf,把目录权限都落到redis用户上。这样就算redis被入侵或配置出问题,攻击面也只是redis用户,而不是root。离线环境的服务器通常运维周期长,这种基础安全习惯值得从一开始就做好。使用Docker部署时同理,容器内也不要随便用root跑主进程。
日志目录要确认有写入权限。redis.conf里配置的logfile路径,如果父目录不存在,redis启动时会直接报错,而且因为日志文件没建起来,这个报错还不一定好发现。我调整配置后,会先手动启动一次前台模式,确认日志能正常写入,再切回systemd管理,避免把问题藏到服务阶段。
5. 离线安装翻车实录:我把踩过的坑按影响面排了个序
5.1 编译失败先看这几类:gcc、make、内存分配器
离线环境下编译redis最容易遇到的错误,是fatal error: jemalloc/jemalloc.h: No such file or directory。这行报错看起来像是缺少jemalloc库,实际上没那么严重。Redis源码编译时默认使用jemalloc,但源码包里并没有自带它的系统头文件,所以如果系统环境缺少相关开发包,就会在这里断掉。处理方式可以这样:重新编译时,改用libc的默认内存分配器。
make MALLOC=libc有时候还要先把之前编译产生的临时文件清理掉,执行make distclean,再带参数重新编译。这个参数的本质是选择redis运行时使用的内存分配器,jemalloc在内存碎片处理上更好,但如果系统没有,用libc也已经能跑,只是长时间高负载下,内存碎片的表现可能不如jemalloc。能装jemalloc就装,装不上就先用libc,不要在编译这步卡太久。
编译阶段还有一个常见问题是server.c: fatal error: openssl/ssl.h: No such file or directory。这是开启TLS支持时找不到OpenSSL开发头文件导致的。要解决,一是补装openssl-devel/libssl-dev,二是在编译时关闭TLS:
make BUILD_TLS=no具体怎么选,取决于你的redis有没有对外提供加密连接的需求。内网纯业务调用,可以先关掉TLS,以后有需求再重新编译。如果一开始就把TLS相关的依赖补齐,后续会灵活一些,但离线环境下依赖越多,准备成本越高,我一般建议按需开启。
5.2 启动了却连不上:bind、protected-mode和防火墙
“明明启动成功了,远程却连不上”是离线部署里被问得最多的问题。第一次遇到时,别急着怀疑redis坏了,按顺序排查三件事:第一,redis.conf里bind的IP到底监听在哪里,用netstat -tlnp | grep 6379看看,如果监听地址是127.0.0.1,那外部机器自然连不上;第二,protected-mode是否拦住你,默认配置在没有密码且没有显式bind内网IP时,会拒绝非本机连接,解决办法就是配置bind或者requirepass;第三,防火墙规则是否放行6379端口,执行firewall-cmd --list-all或iptables -L -n看有没有相关规则。
我在实际排查中还遇到过一个隐藏问题:服务器上有多个网卡,bind写的是业务网卡的IP,但客户端用的却是管理网段的IP,导致连接超时。这种问题不是redis本身的问题,而是网络规划上的理解差异。建议部署前把服务器所有网卡IP列出来,业务方确认访问路径走哪张网卡,再反推bind配置。离线环境里通常没有内网DNS,IP规划要尽量写清楚,免得后续交接时留下模糊地带。
还有一个不常见但特别折腾的坑:系统开启了SELinux,redis监听非标准端口时被SELinux挡住,systemd报启动成功,但外部连接全部超时。这类问题排查起来比较绕,可以用ausearch -m avc -ts recent查看SELinux的拒绝日志。如果确认是SELinux问题,要么把SELinux切到permissive,要么给redis的端口和目录配置对应的SELinux策略,后者虽然麻烦,但在安全要求严格的公司里是必经之路。
5.3 启动日志里的内存警告,不能视而不见
第一次看到redis日志里刷出内存相关的WARNING时,很多人会忽略,实际上这些警告在细水长流的运行中会造成明显问题。最典型的三条:
vm.overcommit_memory=0会产生内存过载风险,建议设为1。transparent hugepage开启时,Redis在fork子进程做持久化时性能波动会变大,建议关闭。net.core.somaxconn太小,高并发下连接可能被丢弃,建议调大。
离线环境下没有在线文档随时查,所以我习惯提前把这些sysctl参数写进/etc/sysctl.conf,一次性到位:
vm.overcommit_memory = 1 net.core.somaxconn = 1024关闭透明大页,不同发行版的写法略有不同,CentOS/RHEL通常直接修改/sys/kernel/mm/transparent_hugepage/enabled,改成never,同时写进rc.local或者sysctl相关配置,确保重启后还生效。透明大页和redis的fork、内存page rewrite机制冲突明显,尤其是开启RDB+AOF双重持久化时,很容易出现写操作延迟抖动。
内存方向的调整一定要结合实际内存大小。如果服务器内存本身只有4G,而redis的maxmemory配到3G以上,系统剩余内存就很紧张,触发swap后性能断崖下跌。设置maxmemory时,我一般预留总内存的20%给操作系统和文件缓存,再把剩余部分合理分配给redis和其持久化开销。离线环境下没有压测工具来得及适应,分配策略就按保守来。
5.4 离线环境缺少依赖库时的绕行方案
依赖库缺失,在编译阶段最容易暴露,在运行阶段也有可能暴露。运行redis时如果提示找不到某个共享库,比如libcrypto.so,先执行ldd /opt/redis-7.4.0/bin/redis-server,看它依赖哪些库,缺哪个就补哪个。补库的常见方式,仍然是从同版本同架构的系统上拷贝libcrypto.so.*,放到/usr/lib64/或/usr/lib/下,再执行ldconfig刷新缓存。
但这里我要提醒一句:拷贝so文件属于临时招,除非公司内部已经有统一的基线,否则不要轻易从一台机器往另一台机器拷系统库。不同发行版对.so的版本、软链接和符号路径要求不一样,很容易出现拷贝后版本冲突。更稳妥的做法还是用系统原生的rpm/deb包离线安装,实在找不到同名版本,再考虑从同发行版同小版本的镜像提取。这也是我前面反复强调“离线部署前先把OS版本看准”的原因。我在这类问题上吃过亏,拷过来的so把系统glibc弄乱,最后只能动用备份,代价很大。
6. 我在多次离线部署中总结的三条心得
离线装redis这件事,很多细节都是靠一次次的现场记录攒出来的。第一条心得是:首次部署时就把“实施笔记”写成文档,把用到的命令、改了哪些配置、依赖的rpm包来源都列清楚。在线环境下随时可以查文档,离线环境一旦中间隔了几个月,再回头排查问题,这份笔记就是最好的参考。我自己就在交付文档里吃过亏,当时图省事没记录编译参数,三个月后要扩容新节点,只能重新逆向排查配置来源。
第二条心得是:不要把“能启动”当成部署结束,一定要做一轮简单的连通性测试和重启持久化测试。我会依次执行redis-cli ping确认可以响应,再写一个key、读一个key验证读写正常,最后执行systemctl restart redis验证开机自启和服务重启恢复。哪怕只是十秒钟的验证,也比后面业务同学找到我们说“redis挂了”强。离线环境的维护窗口比较短,提前验证完,后面就省心。
第三条心得,是关于版本选择。如果公司内部有多个项目,尽量统一Redis版本,别这台7.0、那台7.4,配置文件也要尽可能一致。离线环境没有yum源自动升级,版本多了维护成本是成倍增长的。Redis有个特点是向前兼容做得不错,但配置参数的迁移还是会带来额外工作量。我现在的做法是:新项目统一用7.4.0,老项目慢慢迁移,配套的数据目录、日志目录、systemd模板全部做成标准模板,新服务器上线直接套用。把这些基础工作沉淀下来,离线部署redis就不再是“每次都要踩一遍坑”的苦活了。