Linux 上装 Redis 这事儿,看着简单,实际动手总会遇到几个“经典坎儿”:编译报错、装完不知道服务到底起没起来、重启服务器后 Redis 又不见了。我最初接触 Redis 时也是从这几个坑里爬出来的,所以这次把完整安装流程和三种启动方式一次性讲清楚,你照着走一遍,后面再遇到相关场景基本不用再翻文档。
这篇文章适合刚接触 Linux 和 Redis 的开发者,也适合部署过几次但仍然对启动方式一知半解的运维朋友。我会从源码编译安装讲起,再到前台启动、后台守护进程启动、systemd 开机自启,每一步都给出命令、配置和验证手段,最后把常见报错整理成速查表。全文以我实际踩过的坑为主线,尽量不说废话。
1. 安装前的环境准备与源码下载
1.1 先检查机器状态,别等编译到一半才发现缺东西
很多人在装 Redis 时习惯直接开干,结果make跑到一半报gcc: command not found,或者干脆提示cc不存在,这时候再回头补环境,浪费时间不说,还容易把编译残留搞乱。所以安装前先做三件小事:确认系统版本、检查编译工具链、确认网络能拉到源码包。
# 查看操作系统发行版和内核 cat /etc/os-release uname -a # 检查编译工具链是否齐全 which gcc which make which cc如果输出里缺了gcc或make,先用包管理器装上。不同发行版命令不一样,常见场景下面这两条可以覆盖大多数情况:
# CentOS / Rocky / Amazon Linux sudo yum install -y gcc make # Debian / Ubuntu sudo apt update && sudo apt install -y build-essential这里有一个小细节:build-essential在 Debian 系里是一个元包,会一次性装好 gcc、make、libc 开发头文件等一堆编译必需的东西,比单独装 gcc 更省心。CentOS 系则没有对应的元包,yum groupinstall "Development Tools"也可以达到类似效果,但我嫌它装太多,直接yum install -y gcc make对编译 Redis 来说已经足够。
1.2 下载源码包:为什么不直接用包管理器安装
有朋友会问:apt install redis-server一条命令不就完事了吗?确实能装上,但包管理器装的 Redis 有几个问题:版本往往滞后于官方最新稳定版,路径分散在系统的各个标准目录里(/usr/bin、/etc/redis、/var/log),如果你以后要管理多套环境、定制配置,这种“黑盒”安装方式会限制灵活性。源码编译安装的最大价值在于:安装目录完全可控,版本完全可控,编译选项完全可控。所以我一直推荐自己编译。
下载源码包的位置是 Redis 官网的下载页,稳定版一般以redis-stable.tar.gz的形式提供。在服务器上直接用 wget 或 curl 拉取即可:
cd /opt wget https://download.redis.io/redis-stable.tar.gz tar xzf redis-stable.tar.gz cd redis-stable解压后目录名一般是redis-stable,里面的文件结构大概是这样的:src/是源码主目录,redis.conf是默认配置文件模板,utils/里有些辅助脚本,README.md是个好东西,官方把编译方式、基本用法都写在里面。我建议你先花两分钟cat README.md,比网上翻教程快得多。
2. 编译安装:三行命令搞定,但里面有两个关键点
2.1 编译原理与常见报错
Redis 用 C 语言编写,本身没有configure脚本,这是它和很多其他开源软件不一样的地方。大多数 C 项目要经过./configure && make && make install三部曲,Redis 直接make就行,因为它把平台相关的检测都写在了src/Makefile里,make会自动完成编译配置、依赖检查、可执行文件生成。
make这一步默认使用系统的 gcc 编译。如果你在比较老旧的机器上操作,可能会遇到malloc.h相关的报错,这是 jemalloc 内存分配器和系统库冲突导致的。解决办法是在 make 时指定使用 libc 自带的内存分配器:
make MALLOC=libc这里简单解释一下为什么会出这个错:Redis 默认使用 jemalloc 作为内存分配器,用来减少内存碎片、提升性能。但 jemalloc 的源码有时会检测到不在它支持列表里的平台或 glibc 版本,然后报错。MALLOC=libc的意思是“兄弟我不较真了,就用系统默认的 malloc”,对绝大多数业务场景来说性能差异几乎感觉不到。
编译成功后,src/目录下会出现一系列可执行文件,其中最关键的是:
redis-server:服务端主程序redis-cli:命令行客户端,平时测试、管理全靠它redis-benchmark:性能压测工具redis-check-aof/redis-check-rdb:持久化文件修复工具
2.2 安装到指定目录:这一步决定了你后面好不好管理
编译成功后,我习惯不直接make install装到系统默认路径,而是指定 PREFIX,把 Redis 集中放一个目录里:
make install PREFIX=/usr/local/redis执行完这行,Redis 的可执行文件会被复制到/usr/local/redis/bin/下面。这样做的好处是:以后要卸载直接删这个目录就行,不会在系统里留一堆零散文件;多环境并存时也能清楚区分版本。
Redis 的默认配置文件redis.conf不会自动复制到安装目录,需要手动操作:
mkdir -p /usr/local/redis/conf cp /opt/redis-stable/redis.conf /usr/local/redis/conf/redis.conf验证一下安装结果:
/usr/local/redis/bin/redis-server --version能看到版本号输出,基本就算安装成功。我习惯顺手把/usr/local/redis/bin加进 PATH,省得每次敲全路径:
echo 'export PATH=/usr/local/redis/bin:$PATH' >> /etc/profile.d/redis.sh source /etc/profile.d/redis.sh2.3 安装目录布局规划
很多教程装完就完事,目录里只有bin,其他什么都没。我建议在安装目录下按功能建好子目录,后面维护会非常顺手:
mkdir -p /usr/local/redis/{bin,conf,data,logs,run}bin:可执行文件conf:配置文件data:持久化文件(RDB 快照、AOF 日志)logs:运行日志run:PID 文件
这套布局在接下来的每一种启动方式里都会用到,提前建好能少踩不少坑。
3. 三种启动方式详解:从临时调试到生产自启
3.1 第一种:前台启动,适合测试和应急调试
前台启动是最原始的方式,直接运行redis-server,不带任何参数:
/usr/local/redis/bin/redis-server启动后会看到一段 ASCII 艺术 Logo、版本号、端口号 6379、进程 ID 等信息。此时 Redis 进程在前台运行,终端被“占住”,所有日志直接打印在当前终端里。想验证它是否正常,另开一个终端执行:
redis-cli ping返回PONG就说明服务正常。这个启动方式最大的特点是“所见即所得”,日志实时刷新,调试时非常直观。但它的缺点也很明显:一旦关掉终端窗口或者按Ctrl + C,进程立刻结束。你也不可能在服务器上一直开着一个终端挂着它。所以前台启动这种方式,我只推荐用在以下两个场景:
- 刚装完 Redis,快速验证功能是否正常
- 临时排查问题,需要在前台看完整日志输出
前台启动的关闭方式也很直接:Ctrl + C或在另一个终端执行redis-cli shutdown。
3.2 第二种:后台守护进程启动,日常部署的常用形态
前台启动没法长期驻留,于是需要让 Redis 在后台默默运行。这里“后台运行”指的是守护进程(daemon)模式:启动命令返回后,终端恢复可用,Redis 在系统后台继续运行,不依赖任何终端会话。
要启用这种模式,需要修改配置文件。打开刚才复制好的redis.conf,找到下面几个关键配置项并修改:
vim /usr/local/redis/conf/redis.conf# 将 daemonize 设置为 yes,让 Redis 以守护进程方式运行 daemonize yes # 指定 PID 文件路径,Redis 会把进程号写到这里 pidfile /usr/local/redis/run/redis_6379.pid # 指定日志文件路径,后台模式没有终端可输出,日志必须落到文件 logfile /usr/local/redis/logs/redis_6379.log # RDB 持久化文件默认写到配置文件的相对路径,建议指定绝对路径 dir /usr/local/redis/data然后以配置文件方式启动:
/usr/local/redis/bin/redis-server /usr/local/redis/conf/redis.conf启动后终端立刻返回,看起来什么都没发生。验证是否启动成功:
# 检查进程是否存在 ps -ef | grep redis-server # 检查端口是否监听 ss -tlnp | grep 6379 # 查看 PID 文件 cat /usr/local/redis/run/redis_6379.pid这三个命令任意一个能确认 Redis 在运行,基本就稳了。此时 Redis 进程已经脱离终端,即使你退出 SSH 会话,它也会继续运行。停止 Redis 的标准方式是使用客户端命令:
redis-cli shutdown这个命令不能乱发,它会触发 Redis 保存数据然后退出,比直接 kill 进程更安全。如果你只是想立刻结束,也可以kill -9全体 Redis 进程,但那样可能导致数据丢失,非紧急情况不推荐。
后台守护进程模式是很多传统运维场景里的标准做法,它的优点是部署简单、可控性好,缺点是服务器重启后需要手动再次启动,对生产环境来说还不够“自动”。
3.3 第三种:systemd 服务管理,生产环境开机自启的推荐方案
现代 Linux 发行版都使用 systemd 作为 init 系统,把 Redis 托管给 systemd 就能实现开机自启、异常自动拉起、统一日志管理等能力。这种方式是我目前在生产环境里最推荐的做法。
先创建 systemd 服务文件:
vim /etc/systemd/system/redis.service[Unit] Description=Redis persistent key-value database After=network.target [Service] Type=simple ExecStart=/usr/local/redis/bin/redis-server /usr/local/redis/conf/redis.conf --daemonize no ExecStop=/usr/local/redis/bin/redis-cli shutdown Restart=on-failure [Install] WantedBy=multi-user.target写这个服务文件有五个关键点必须理解,否则启动会失败或埋下隐患:
关键点一:为什么要加--daemonize no
这是新手最容易踩的坑。如果redis.conf里设置了daemonize yes,Redis 启动后父进程会 fork 一个子进程出来,然后父进程退出。而 systemd 的Type=simple模式下,systemd 判断“服务是否还在运行”的依据就是启动的那个进程是否存活。现在父进程退出了,systemd 会认为 Redis 已经停止,于是出现“启动一下立刻失败”的现象。所以必须在命令行参数里加--daemonize no覆盖配置文件的设置,让 Redis 在前台运行,由 systemd 直接管理。
关键点二:Type=simplevsType=forking
我特意没有用Type=forking,这是很多老教程里的写法。forking模式要求程序自己后台化,然后通过PIDFile让 systemd 找到子进程 PID。这个模式对 Redis 也能用,但需要额外配置 PIDFile,并且如果 PID 文件路径写错或更新不及时,systemd 的状态判断会出问题。相比之下simple模式更简单更可靠。
关键点三:ExecStop为什么用redis-cli shutdown
redis-cli shutdown是 Redis 官方的优雅退出命令,会先触发持久化再把进程结束掉。如果不设置 ExecStop,systemd 默认会给进程发 SIGTERM,Redis 收到 SIGTERM 也能优雅退出,但显式声明 ExecStop 更保险,还能保证systemctl stop redis时走的是正规关闭流程。
关键点四:Restart=on-failure
这个配置让 Redis 在异常退出时自动被 systemd 重新拉起来。比如内存不足导致进程被杀,只要系统还能响应,systemd 就会尝试重启 Redis。这比我们手动盯进程靠谱得多。
关键点五:After=network.target
Redis 虽然不依赖网络服务才能启动,但监听端口需要网络已就绪。声明After=network.target确保网络服务先启动完成,避免启动时因为网络未初始化导致端口绑定失败。
写好服务文件后,正式启用:
# 重新加载 systemd 配置,通知 systemd 有新的服务文件 systemctl daemon-reload # 设置开机自启 systemctl enable redis # 立即启动 systemctl start redis # 查看运行状态 systemctl status redisstatus输出里能看到Active: active (running)以及进程主 PID、内存占用、日志片段等信息。以后日常管理用下面几条命令:
systemctl status redis # 查看状态 systemctl restart redis # 重启 systemctl stop redis # 停止 systemctl disable redis # 取消开机自启配合 systemd 的日志机制,查看 Redis 日志不再需要tail -f日志文件:
journalctl -u redis -f这条命令实时查看 Redis 的 systemd 日志输出,排查问题比翻文件方便很多。
4. 三种启动方式的对比与生产选型建议
4.1 三张卡片的对比表
把三种方式放在一起对比,优劣就很明显了:
| 对比项 | 前台启动 | 后台守护进程 | systemd 托管 |
|---|---|---|---|
| 启动命令 | redis-server | redis-server + 配置文件 | systemctl start redis |
| 是否依赖终端 | 是,关闭终端进程退出 | 否 | 否 |
| 开机自启 | 不支持 | 需额外配置 | 原生支持 |
| 进程崩溃恢复 | 无 | 无 | 自动重启 |
| 日志方式 | 终端直接输出 | 日志文件 | journald 统一收集 |
| 停止方式 | Ctrl+C / redis-cli shutdown | redis-cli shutdown | systemctl stop redis |
| 适用场景 | 临时调试、功能验证 | 无 systemd 的旧系统或容器内 | 生产环境首选 |
4.2 我心中的生产环境最佳组合
如果你的服务器是 CentOS 7 以上、Ubuntu 16 以上这种带 systemd 的现代发行版,直接使用第三种方式,并且把 systemd 服务配置里--daemonize no和Type=simple搭配使用。这既保证了开机自启和自动恢复,又避免了 forking 模式的 PIDFile 麻烦。
有些老系统还在用 SysV init,没有 systemd,那时候退而求其次用第二种后台守护进程方式,配合rc.local或crontab @reboot也能实现开机自启,但维护成本更高。如果你是容器环境(比如 Docker),通常不需要容器内再跑一个 systemd,直接把 redis-server 作为容器主进程前台运行,这其实就是第一种启动方式的思路。所以“三种方式孰优孰劣”最终取决于运行环境,没有绝对的银弹。
4.3 用 Redis 用户运行服务:生产环境的最后一步加固
我在生产环境里还会做一步额外操作:创建一个专用系统用户来跑 Redis,而不是用 root 身份运行。虽然 Redis 官方允许 root 启动,但安全上始终是个隐患——万一服务被利用,攻击者可能拿到更大的权限。
# 创建系统用户,不允许登录 useradd -r -s /sbin/nologin redis # 给 Redis 安装目录设置属主 chown -R redis:redis /usr/local/redis然后回到/etc/systemd/system/redis.service的服务配置,增加两行:
User=redis Group=redis修改完成后:
systemctl daemon-reload systemctl restart redis这样 Redis 进程就以 redis 用户身份运行了。注意data和logs目录也必须在 redis 用户有权限的路径下,不然持久化和日志写入都会失败。用ps -ef | grep redis-server看一眼启动用户,确认不是 root,这一步就算到位了。
5. 常见问题与排查技巧实录
5.1 编译阶段问题速查
问题:make时报gcc: command not found
原因很简单,没装编译工具链。执行前面第一节里的 yum 或 apt 命令安装即可。我遇到过一种特殊情况:gcc 装了但版本特别老,编译时识别不了新的 CPU 指令导致.c文件内部错误,这时候建议升级 gcc。
问题:make报Missing separate debuginfos或jemalloc相关错误
典型的内存分配器问题。运行make distclean清理编译缓存后,重新用make MALLOC=libc编译。make distclean这一步很重要,不要直接重新 make,否则旧的编译中间文件会继续干扰。
问题:make install PREFIX后找不到 redis-server
确认你执行make install时是在 Redis 源码目录内。如果是在别的目录执行的,会报“没有规则可以创建目标”之类的错误。另外 PREFIX 指定的父目录必须已经存在,/usr/local/redis不存在时 make install 并不会自动创建完整的父级目录。
5.2 启动阶段问题速查
问题:启动后立刻退出,日志显示Can't open the log file: Permission denied
多半是 logfile 路径所在的目录没有写权限。检查/usr/local/redis/logs的属主和权限,或者直接用chown redis:redis修正。如果日志配置是logfile "",Redis 会把日志输出到标准输出,配合 systemd 就是 journalctl 里才能看到。
问题:redis-cli ping报Could not connect to Redis at 127.0.0.1:6379: Connection refused
先用ss -tlnp | grep 6379确认端口有没有监听。如果端口没监听,大概率配置有误导致启动失败,查看日志文件。如果端口在监听但还是连不上,检查protected-mode和bind配置。Redis 默认配置里bind 127.0.0.1只允许本机连接,需要外部访问时必须修改 bind 为实际网卡 IP,同时设置密码(requirepass)关闭保护模式。不建议直接把protected-mode改成 no,这样裸奔很危险。
5.3 systemd 管理阶段问题速查
问题:systemctl start redis后立刻显示 inactive
十有八九是Type=simple和daemonize yes撞了。要么在配置文件里改daemonize no,要么在 ExecStart 里加--daemonize no。改完记得systemctl daemon-reload。
问题:systemctl enable redis报错Failed to create symbolic link
服务文件的[Install]段缺失或写错。检查WantedBy=multi-user.target是否在。enable操作本质上是把 redis.service 链接到/etc/systemd/system/multi-user.target.wants/目录下,没有 [Install] 段 systemd 不知道该把服务链接到哪个 target。
问题:Redis 每隔一段时间就自动重启
先从journalctl -u redis -e看退出原因,如果是Killed,大概率是被 OOM Killer 杀了。这种情况去排查系统的内存压力,不要再盲目加大maxmemory配置,该扩容或者调优业务优先。Restart=on-failure的意义就在这里——它能保证服务被误杀后快速恢复,但不能治愈根因。
5.4 数据安全相关的隐藏深坑
最后提醒一个容易被忽略的配置项:dir。Redis 的 RDB 快照和 AOF 文件默认写到启动时的工作目录,如果你是从源码目录启动的,持久化文件会散落在那个临时目录里,以后源码目录被清掉,数据就没了。这也是我在 2.3 节专门建data目录的原因。配置好:
dir /usr/local/redis/data后,重启一次 Redis,然后可以用redis-cli save手动触发一次持久化,再进入 data 目录确认dump.rdb文件生成了。这一步没问题,说明持久化路径配置正确。
6. 再聊几句:日常维护里我养成的几个习惯
装好 Redis、选好启动方式只是第一步,日常维护里我逐渐养成了一些小习惯,分享出来可能对你也有帮助。
第一,不在命令行里直接执行redis-server &或者用nohup redis-server &这种野生后台方式。这类方式虽然也能让进程留在后台,但没有统一的管理入口,进程状态全靠肉眼去 ps 找,出了问题很难排查。无论用哪种方式启动,一定要让 Redis 进程能被查询到、能被标准命令关闭。
第二,我把重要的 Redis 参数做了基线模板放在/usr/local/redis/conf/redis.conf里,每次安装新服务器直接从模板复制再微调。模板里包含稳定的内存上限、合理的连接数限制、必要的持久化策略。比如maxmemory 2gb加上maxmemory-policy allkeys-lru这种组合,可以在内存满的时候不至于直接 OOM,而是按策略淘汰旧数据。
第三,定期用redis-cli info看看内存碎片率、命中率这些指标。碎片率在 1.0 到 1.5 之间算正常,持续高于 1.5 就得考虑重启或调整activedefrag。这些指标老手一般都知道,但新手容易忽略,列出来当个备忘。
第四,服务器安全组和防火墙别把 6379 端口裸露到公网。如果业务确实需要远程访问,必须给 Redis 设置高强度密码,并且建议用 ACL 用户体系做权限隔离,而不是直接复用默认的requirepass。
装 Redis 从来不是“装完就跑”这么简单,启动方式的选择直接影响服务可用性和排障效率。按这套流程走下来,源码编译、目录规划、systemd 托管、用户权限隔离都到位了,后面基本不会再来回折腾。这套东西我自己在测试环境和生产环境都验证过,照着做能少踩很多坑。