Linux Redis 安装三条路线:源码编译、包管理器与 Docker 避坑指南
2026/9/18 11:18:55 网站建设 项目流程

Redis 在 Linux 上的安装,几乎是后端入门的第一次"手感训练"——命令没几条,但每一步背后都藏着坑。我见过太多人照着某篇三年前的教程敲完make install,结果redis-cli死活连不上,日志里一行 protected-mode 的提示就把人卡住半天;也见过有人用包管理器两分钟装完,上线时才发现版本是 Redis 5.x,业务里用的 Stream 类型根本不认。

这篇东西不讲虚的,目标就一个:让你在一台干净的 Linux 机器上把 Redis 真正装起来、跑起来、并且能长期跑下去。源码编译、包管理器、容器这三条路线我都会给完整实操过程,不管你是刚背 Linux 常用命令的新手,还是要给生产环境做部署的老手,都能在里面找到对应阶段的细节——编译参数为什么这么选、redis.conf 里每一行的作用、systemd 托管文件怎么写、内存和持久化怎么配、以及各类报错现场到底是怎么修好的。

先提前说清楚一个前提:Redis 安装从来不是"敲三条命令"的事,而是"选版本、选安装位置、选启动方式、选安全策略"这一串决策的结果。下面按这个顺序拆。

1. 动手之前先把路线定下来

1.1 你到底要的是"能跑"还是"能长期跑"

这是最容易被跳过的一步。很多人上来就问"Redis 怎么装",但这个问题本身是残缺的——装在本机做开发调试,和装在生产服务器上扛流量,需求完全不一样。

开发环境要的是快:两分钟能起一个实例,改配置重启方便,数据丢了也无所谓。生产环境要的是稳:版本可控、配置可追溯、开机自启、内存有上限、持久化有策略、端口不裸奔。你如果拿开发环境那套"apt install完事"的思路去装生产库,后面一定会在某个凌晨三点被叫起来。

所以我的建议是先回答三个问题:这台机器是开发机还是服务器;你需要的 Redis 版本号是多少(业务依赖了什么特性);这台机器上还有没有别的东西要跑。三个问题回答完,路线基本自己就浮出来了。

1.2 源码编译安装:可控性最高,代价是编译阶段容易翻车

源码编译是我在服务器上最常用的方式,理由很直接:版本完全由我说了算,安装路径完全由我说了算,编译时可以按需开关 TLS、jemalloc 这些选项,将来升级也只需要换一个源码目录。

代价也很明确。第一是依赖问题,缺少 gcc、make、tcl 的时候编译直接中断;第二是 CentOS 7 这类老系统自带 gcc 4.8.5,编译 Redis 7 会因为 C11 标准支持不足报错,得先升级工具链;第三是编译过程吃内存,小内存机器上make被 OOM Killer 干掉的情况我遇到过不止一次。

不过这些坑都是一次性的,装通一遍之后你会对整个 Redis 的组成结构清楚很多。真正做运维或者做后端开发,我建议至少完整手动编译过一次。

1.3 包管理器安装的版本陷阱

apt install redis-server或者yum install redis,这是最快的路径,也是最容易埋雷的路径。发行版仓库为了稳定性,会把软件版本长期冻结在一个老版本上。Ubuntu 22.04 自带的 Redis 是 6.0.x 这个量级,Debian 12 大概是 7.0.x,而主线版本早就跑到 7.4 往上了。

这中间差的可不只是小版本号。Redis 6 引入了 ACL 和多线程 IO,Redis 7 引入了 Functions 和分片式 AOF 重写,如果你写的代码用了这些特性,而线上跑的是老版本,本地测试通过、上线直接报错,这种问题排查起来极其折磨人。

所以包管理器安装适合两种人:一种是本地随便跑跑的开发者,一种是明确知道自己只需要基础 KV 能力、且不想维护编译环境的团队。如果你属于这两种,用发行版仓库没问题,但至少要让仓库里是 Redis 6 以上。

1.4 容器化安装适合什么样的场景

Docker 跑 Redis 的体验确实舒服,一条docker run就完事,版本切换只要改镜像 tag,环境隔离干净,数据目录挂出来也不怕容器被删。现在很多团队的开发环境、CI 环境、甚至部分生产环境都在这么干。

但它有两个必须先想清楚的点。一是网络,容器内的 6379 和你宿主机的 6379 是两回事,端口映射没做好就会出现"容器明明起来了我却连不上"。二是持久化,容器一删数据就没,必须把/data挂载到宿主机目录,而且这个目录的权限要和容器内 redis 用户的 uid 对齐,否则会出现 AOF 写入失败这种诡异问题。

还有一个细节:官方镜像默认是不带配置文件启动的,用的是内置默认配置。你想改参数,要么挂载自己的配置文件,要么用--requirepass这类命令行参数。前者更规范,后面我会给出完整的挂载写法。

1.5 一张表帮你三分钟做决定

对比维度源码编译安装包管理器安装容器化安装
版本可控性完全可控,想装哪个装哪个受发行版仓库限制完全可控,改 tag 即可
首次安装耗时10 到 30 分钟(含编译)2 到 5 分钟3 到 5 分钟
依赖要求gcc、make、tcl、系统库无额外依赖Docker 运行时
升级难度换源码目录重新编译一条命令升级换镜像重启容器
配置灵活性最高,编译期也能调中等高,但要走挂载
适合场景生产服务器、需要特定版本本地开发、基础需求开发环境、CI、微服务配套
常见翻车点编译报错、依赖缺失版本过旧端口映射、数据卷权限

我个人的习惯是:本机开发用包管理器或者容器,服务器上一律源码编译。这不是信仰问题,纯粹是出问题时定位成本更低——所有东西都在我指定的目录里,出了事看日志、看配置、看进程,一目了然。

2. 源码编译安装 Redis:从零到 systemd 托管

2.1 环境检查与编译依赖准备

第一步永远是确认机器状态。登上去先看三件事:系统版本、内存大小、以及到底能不能连外网下东西。

# 看系统版本和内核 cat /etc/os-release uname -r # 看内存,Redis 编译阶段建议至少 1GB 可用内存 free -h # 看 CPU 核数,决定后面 make -j 用几个线程 nproc # 看磁盘空间,编译加源码包建议留 2GB 以上 df -h /usr/local

然后装依赖。Debian 系和 RedHat 系的包名不一样,我把两套都列出来。

Debian / Ubuntu 系:

sudo apt update sudo apt install -y build-essential tcl pkg-config

CentOS / RHEL / Rocky / Alma 系:

sudo yum groupinstall -y "Development Tools" sudo yum install -y tcl tcl-devel

这里解释一下为什么需要这几个东西。gccmake是编译的基础,没有它们make会直接报cc: Command not foundtcl是 Redis 自带的测试套件make test需要的,虽然不做测试可以跳过,但既然装一次,顺手装上更省事。pkg-config主要在链接系统库的时候用得上。

提示:CentOS 7 用户请特别留意,系统自带 gcc 4.8.5 在编译 Redis 6 以上版本时会报unrecognized command line option "-std=c11"之类的问题。这种情况要么升级 gcc,要么换用后面提到的make MALLOC=libc方式绕开部分编译路径,但这个绕法解决不了 C11 支持问题,最终还是得升级工具链。

2.2 下载源码包与完整性校验

我习惯把源码放在/usr/local/src下,这是比较传统的做法,和系统自带的软件目录结构一致,将来找东西方便。

cd /usr/local/src # 下载指定版本的源码包,版本号按需替换 wget https://download.redis.io/releases/redis-7.2.4.tar.gz # 如果服务器没装 wget,用 curl 也一样 # curl -O https://download.redis.io/releases/redis-7.2.4.tar.gz # 校验压缩包完整性 sha256sum redis-7.2.4.tar.gz

下载页面上会给出对应版本的 SHA256 值,把sha256sum的输出和官网给的值逐位对比,一致才继续。这一步很多人觉得多余,但我确实遇到过下载中断导致压缩包不完整、解压到一半报错的情况,校验一下能省掉后面一堆莫名其妙的问题。

注意:如果服务器在受限网络环境里下载特别慢,可以在本地下载好再用 scp 传到服务器,效果是一样的。文件传输完成后同样要做一次 sha256 校验。

校验通过就可以解压了:

tar -zxvf redis-7.2.4.tar.gz cd redis-7.2.4 ls -l

正常的话你会看到srcdepsutilstests这些目录,以及顶层的README.mdredis.confMakefile。这里记住一件事:顶层那个redis.conf是配置模板,后面要复制到我们规划的目录里再用。

2.3 make 编译过程详解与参数选择

编译这一步是整个流程里最容易出问题的环节,所以我把参数说透。

# 进入源码目录 cd /usr/local/src/redis-7.2.4 # 先清理一遍,确保没有历史编译残留 make distclean # 带多核并行编译 make -j$(nproc)

make distclean这一步看着多余,其实很有必要。如果你之前在这个目录编译过一次并失败了,残留的.o文件可能导致下次编译出现莫名其妙的链接错误,先清干净是成本最低的兜底动作。

-j$(nproc)是用上机器的所有 CPU 核心并行编译,能把编译时间从几分钟压到几十秒。

关于MALLOC参数。Redis 默认会使用自带的 jemalloc 内存分配器,需要编译deps/jemalloc这个子目录。这个子目录在某些环境下会编译失败,典型报错是找不到jemalloc/jemalloc.h。这种情况下有两个处理方式:

# 方式一:重新清理后再来一遍,很多时候是上次中断导致的残留问题 make distclean && make -j$(nproc) # 方式二:改用系统自带的 libc 分配器,绕开 jemalloc 编译 make MALLOC=libc

方式二能解决问题,但代价是内存碎片管理能力会弱一些,高并发写入场景下更明显。所以我的建议是优先用方式一排查,实在绕不过去再选方式二。

关于BUILD_TLS如果你的环境需要 TLS 加密连接(比如跨公网传输),编译时要显式开启:

make BUILD_TLS=yes

这需要系统里已经装了 OpenSSL 开发库(libssl-devopenssl-devel)。普通内网使用不需要开这个,开了反而增加配置复杂度。

编译成功的话,最后会看到一句Hint: It's a good idea to run 'make test' ;)。想验证的话可以跑make test,这一步会花几分钟,做的是功能自测。生产环境我一般不会在服务器上跑完整测试,因为耗时且吃资源,但如果你是在本地搭建学习环境,跑一遍很有价值。

2.4 安装目录规划与 make install

编译产物都在src目录下,比如src/redis-serversrc/redis-cli。直接跑也能跑,但那样管理起来太乱。标准做法是用PREFIX参数把可执行文件装到统一目录。

# 指定安装前缀,可执行文件会落到 /usr/local/redis/bin make PREFIX=/usr/local/redis install

执行完看一下目录:

ls -l /usr/local/redis/bin

正常会看到redis-serverredis-cliredis-benchmarkredis-check-aofredis-check-rdbredis-sentinel这几个文件。每个的用途简单说一下:redis-server是服务端主程序;redis-cli是命令行客户端,日常用得最多;redis-benchmark是压测工具;redis-check-aofredis-check-rdb是持久化文件的修复校验工具,出故障时能救命;redis-sentinel是哨兵,做高可用时用。

接着把配置和数据目录建起来。我一般分三个目录:配置、数据、日志。

mkdir -p /usr/local/redis/conf mkdir -p /usr/local/redis/data mkdir -p /usr/local/redis/logs # 从源码目录复制配置模板 cp /usr/local/src/redis-7.2.4/redis.conf /usr/local/redis/conf/ # 建一个专用账号跑 Redis,避免用 root 启动 sudo useradd -r -s /sbin/nologin redis # 把目录属主改掉 sudo chown -R redis:redis /usr/local/redis

注意:千万不要用 root 身份长期运行 Redis。一旦 Redis 出现漏洞被利用,攻击者拿到的就是 root shell。创建独立系统账号是最基本的一道防线,成本几乎为零。

2.5 redis.conf 关键参数逐条拆解

配置文件是这个环节的核心,我挑必须改的和必须懂的说。

vim /usr/local/redis/conf/redis.conf

网络与访问控制部分:

# 监听地址。只允许本机访问就写 127.0.0.1 # 需要被同网段其他机器访问,写内网 IP,不要写 0.0.0.0 bind 127.0.0.1 # 保护模式。默认 yes,在没有密码且没有 bind 的情况下会拒绝外部连接 protected-mode yes # 端口 port 6379 # TCP 连接队列长度,配合内核 somaxconn 调整 tcp-backlog 511 # 客户端空闲超时,0 表示不断开 timeout 0 # TCP 心跳,建议保留 tcp-keepalive 300

bindprotected-mode这两个是最容易出问题的组合。很多人为了图方便把bind改成0.0.0.0,把protected-mode改成no,然后还设了个弱密码——这等于把数据库直接挂在公网上。6379 端口是被扫描最多的端口之一,我强烈建议只监听内网地址,配合防火墙做白名单。

进程与日志部分:

# 是否后台运行。用 systemd 托管时设为 no daemonize no # 让 Redis 以 systemd 模式运行,交给 systemd 接管主进程 supervised systemd # pid 文件位置 pidfile /var/run/redis_6379.pid # 日志级别:debug / verbose / notice / warning loglevel notice # 日志文件,空字符串表示输出到标准输出 logfile "/usr/local/redis/logs/redis.log" # 数据库数量,默认 16 个 databases 16

这里有个关键点值得展开:daemonizesupervised的搭配。如果你手动敲命令启动、想让 Redis 在后台跑,那就daemonize yes。但如果用 systemd 托管,正确做法是daemonize nosupervised systemd,让 systemd 直接持有主进程。否则会出现 systemd 认为服务"启动失败"但进程其实在跑,或者 stop 的时候杀不干净这种问题。这是新手很容易踩的坑。

持久化部分:

# RDB 快照策略:900 秒内至少 1 次写入就存盘 save 900 1 save 300 10 save 60 10000 # 快照失败时是否停止写入,建议 yes,能及时暴露磁盘问题 stop-writes-on-bgsave-error yes # 快照文件是否压缩 rdbcompression yes # 快照文件名 dbfilename dump.rdb # 工作目录,RDB 和 AOF 都放这 dir /usr/local/redis/data # 开启 AOF 持久化 appendonly yes # AOF 刷盘策略:everysec 每秒一次,性能与安全的平衡点 appendfsync everysec # AOF 重写条件 auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb

RDB 和 AOF 的区别我用一个类比说明:RDB 像定期给数据库拍照片,文件小、恢复快,但两次拍照之间宕机会丢数据;AOF 像记账本,每次写操作都记一笔,丢掉的数据极少,但文件会越来越大,需要通过重写来瘦身。生产环境我的经验是两个都开,用 AOF 保数据完整性,用 RDB 做备份和快速恢复。

内存与淘汰策略部分:

# 最大内存,按机器实际内存的 60% 到 70% 设置 maxmemory 2gb # 淘汰策略:内存满了之后怎么处理 maxmemory-policy allkeys-lru # LRU 采样精度,越大越精确但越耗 CPU maxmemory-samples 5

淘汰策略的选择逻辑:如果你的 Redis 是纯缓存,所有 key 都可以丢,用allkeys-lru;如果有一部分 key 是必须长期保留的,就用volatile-lru,只淘汰设置了过期时间的那部分。noeviction是默认值,意思是内存满了直接报错拒绝写入,用在"数据绝对不能丢"的场景,但要做好写入失败的兜底。

安全部分:

# 访问密码,强烈建议设置,且要足够长 requirepass 你的高强度密码 # 危险命令重命名或禁用 rename-command FLUSHALL "" rename-command FLUSHDB "" rename-command KEYS "" rename-command CONFIG "CONFIG_8f2a1c"

禁用FLUSHALLFLUSHDB是因为这两个命令会清空整个库,误操作一次就是生产事故。禁用KEYS是因为它会阻塞主线程遍历所有 key,线上执行一次可能导致几秒的服务中断,替代方案是用SCANCONFIG重命名是为了防止有人远程改配置。

改完配置记得检查一遍语法,然后启动:

/usr/local/redis/bin/redis-server /usr/local/redis/conf/redis.conf

2.6 用 systemd 托管 Redis 并设置开机自启

手动启动的进程一关终端就没了,也不方便管理。正规做法是写一个 systemd 服务单元。

sudo vim /etc/systemd/system/redis.service

内容如下:

[Unit] Description=Redis In-Memory Data Store Documentation=https://redis.io/documentation After=network.target network-online.target Wants=network-online.target [Service] Type=notify User=redis Group=redis RuntimeDirectory=redis RuntimeDirectoryMode=0755 ExecStart=/usr/local/redis/bin/redis-server /usr/local/redis/conf/redis.conf ExecStop=/usr/local/redis/bin/redis-cli -a 你的密码 shutdown Restart=always RestartSec=5 LimitNOFILE=65535 [Install] WantedBy=multi-user.target

几个字段解释一下。Type=notify配合配置里的supervised systemd使用,让 systemd 能准确知道 Redis 什么时候真正准备好了。Restart=always保证进程意外挂掉后自动拉起。LimitNOFILE=65535是文件描述符上限,Redis 官方文档明确建议调高,默认的 1024 在高并发连接下会直接报 "too many open files"。

生效并启动:

sudo systemctl daemon-reload sudo systemctl enable redis sudo systemctl start redis sudo systemctl status redis

看到active (running)就对了。如果显示失败,用journalctl -u redis -n 50 --no-pager看最近 50 行日志,报错信息通常很直白。

2.7 安装结果验证:从 ping 到五大数据类型

最后一步是确认它真的能用,而不只是"进程起来了"。

# 看版本 /usr/local/redis/bin/redis-server -v /usr/local/redis/bin/redis-cli -v # 连接并测试 redis-cli -h 127.0.0.1 -p 6379 -a 你的密码 --no-auth-warning ping

返回PONG就说明连接链路通了。--no-auth-warning是关掉那个"用命令行传密码不安全"的提示,仅用于测试,脚本里不要这么写。

接着把这五种基础数据类型各跑一遍,既验证安装,也顺便熟悉命令:

# 字符串 String SET user:1:name "tom" GET user:1:name # 列表 List LPUSH task:queue "task1" "task2" "task3" LRANGE task:queue 0 -1 # 哈希 Hash HSET user:1 name "tom" age 28 city "hangzhou" HGETALL user:1 # 集合 Set SADD article:1:tags "linux" "redis" "backend" SMEMBERS article:1:tags # 有序集合 ZSet ZADD rank:score 100 "tom" 92 "jerry" 85 "spike" ZRANGE rank:score 0 -1 WITHSCORES

五种类型各有各的适用场景:String 做缓存和计数器,List 做消息队列,Hash 存对象,Set 做去重和交并集,ZSet 做排行榜。装完之后自己动手跑一遍,比看十篇文档都管用。

3. 两条捷径:包管理器与容器安装的完整实操

3.1 Ubuntu/Debian 用 apt 安装

基础安装简单到不像话:

sudo apt update sudo apt install -y redis-server sudo systemctl enable redis-server sudo systemctl start redis-server redis-cli ping

装完之后几个关键路径记一下:配置文件在/etc/redis/redis.conf,数据目录在/var/lib/redis,日志在/var/log/redis/。改配置改/etc/redis/redis.conf,改完sudo systemctl restart redis-server生效。

如果嫌仓库里的版本太老,可以换官方源:

# 导入官方 GPG 公钥 curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg # 添加官方仓库 echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list # 更新并安装 sudo apt update sudo apt install -y redis

这样装到的就是 Redis 官方当前稳定版,比发行版自带的新不少。装完后包名从redis-server变成了redis,systemd 服务名也跟着变,用systemctl status redis-server查状态,这是很多人换源后会懵一下的地方。

3.2 CentOS/RHEL 用 yum/dnf 安装

# 先装 EPEL 扩展仓库 sudo yum install -y epel-release # 安装 Redis sudo yum install -y redis # 启动并设置开机自启 sudo systemctl enable redis sudo systemctl start redis redis-cli ping

CentOS 系的配置文件在/etc/redis.conf(注意不是/etc/redis/redis.conf,路径和 Debian 系不一样)。RHEL 8 以上系统yum其实就是dnf的软链,命令可以直接通用。

整体流程不复杂,但依赖第三方仓库,用之前建议先确认一下要装的版本。yum info redis能看到仓库里提供的版本号和来源。

3.3 Docker 跑一个生产可用的 Redis 实例

容器方式看着简单,但要配得像样,还是得挂配置文件和数据卷。

# 拉镜像,指定具体版本,不要用 latest docker pull redis:7.2.4 # 建宿主机目录 mkdir -p /data/redis/conf mkdir -p /data/redis/data # 从官方镜像里拷一份配置模板出来 docker run --rm redis:7.2.4 cat /usr/local/etc/redis/redis.conf > /data/redis/conf/redis.conf # 按需修改配置,至少改这三项 # daemonize no # bind 0.0.0.0 (容器内需要监听所有地址,外部访问靠端口映射控制) # dir /data vim /data/redis/conf/redis.conf # 启动容器 docker run -d \ --name redis \ --restart always \ -p 127.0.0.1:6379:6379 \ -v /data/redis/conf/redis.conf:/usr/local/etc/redis/redis.conf \ -v /data/redis/data:/data \ redis:7.2.4 \ redis-server /usr/local/etc/redis/redis.conf

几个细节必须说清楚。端口映射我写的是127.0.0.1:6379:6379,意思是只在宿主机本地监听,外部机器连不上,这是最安全的做法,需要外部访问时再改成内网 IP。--restart always保证容器随 Docker 服务自动拉起。数据卷必须挂/data,否则容器重建数据就没了。最后一行指定了配置文件路径,不写的话 Redis 会用内置默认配置启动。

注意:挂载配置文件时,宿主机上的文件必须已经存在,否则 Docker 会把它当成目录创建,导致容器启动报错。这是个非常经典的坑。

3.4 顺手把主从复制搭起来

单机部署之后,很多时候下一步就是主从。原理很简单:从节点连上主节点,同步全量数据,之后持续接收增量。配置上只需要在从节点的配置文件里加一行:

# 在从节点的 redis.conf 中 replicaof 主节点IP 6379 # 如果主节点设置了密码,从节点必须配上,否则同步会失败 masterauth 主节点密码

改完重启从节点,然后用redis-cli info replication查看状态。主节点上会看到connected_slaves:1,从节点上会看到master_link_status:up。如果显示down,八成是masterauth没配对,或者防火墙拦了 6379 端口。

主从搭起来之后,读请求可以分摊到从节点,同时也具备了一定的容灾能力(虽然还需要哨兵做故障自动切换)。

3.5 三种安装方式横向对比

项目源码编译包管理器Docker
配置文件位置自定义,如 /usr/local/redis/conf/etc/redis/redis.conf挂载到宿主机指定目录
数据目录自定义,如 /usr/local/redis/data/var/lib/redis容器内 /data,挂载出来
服务管理手写 systemd unit安装时自带docker restart 策略
升级方式重新编译安装包管理器升级换镜像 tag
排查便利性高,所有路径都在掌控内依赖 docker logs
隔离性差,和系统共享环境

4. 装完之后必须做的四件事

4.1 安全加固:密码只是第一步

很多人的安全认知停留在"设个密码就完事",实际上这只是最低门槛。我按优先级列几条。

第一,永远不要监听公网。bind写内网地址,配合防火墙白名单。Redis 在没有任何防护的情况下暴露公网,被植入挖矿程序的案例多到数不清。

第二,密码要够长。8 位以下的密码在离线爆破面前撑不了多久。用 32 位随机字符串,存在配置文件的权限要设成 600。

chmod 600 /usr/local/redis/conf/redis.conf chown redis:redis /usr/local/redis/conf/redis.conf

第三,用 ACL 做细粒度权限。Redis 6 以后支持 ACL,可以给不同的应用分配不同账号,限制能访问的 key 前缀和能执行的命令。这是比单一密码更合理的做法:

# 创建一个只能读 app1 前缀 key 的账号 ACL SETUSER app1_read on >强密码 ~app1:* +@read # 查看现有账号 ACL LIST

第四,考虑改端口。这个措施只能减少被扫描命中的概率,属于"降低噪音"级别的防护,不能替代密码和防火墙,但成本低,顺手做一下没坏处。

4.2 RDB 与 AOF:持久化怎么选怎么配

持久化配置直接决定宕机后你会丢多少数据。我把两种方式的特性列一下。

维度RDBAOF
文件形式二进制快照追加写日志
文件大小小,压缩后更小大,需要定期重写
恢复速度相对慢
数据丢失风险可能丢几分钟最多丢 1 秒
对性能影响子进程 fork,瞬间内存翻倍每写一次有刷盘开销
适合场景备份、灾备数据可靠性要求高

我的实际配置通常是两个都开:RDB 用来做定期备份,AOF 用来保证数据不丢。同时要注意maxmemory的设置不能太激进,因为 RDB 存盘时fork子进程需要额外的内存空间,如果maxmemory设成了物理内存的 90%,存盘时极有可能触发 OOM,导致 Redis 被杀掉。

Redis 7 的 AOF 采用了多文件机制,会生成appendonly.aof.1.base.rdb这样的基础文件加上增量文件,这个目录不要手动去动,需要修复时用redis-check-aof工具。

4.3 内存上限与淘汰策略

maxmemory不设的话,Redis 会一直吃内存直到把机器吃爆。我的一般原则是单实例不超过物理内存的 60% 到 70%。如果开了 RDB 持久化,再往下压一点,给 fork 留出空间。

淘汰策略一共 8 种,常用的就是表格里这几个:

策略含义适用场景
noeviction内存满时拒绝写入并报错数据不能丢的场景
allkeys-lru所有 key 中淘汰最久未使用的纯缓存场景
allkeys-lfu所有 key 中淘汰访问频率最低的有明显冷热数据的缓存
volatile-lru只从设了过期时间的 key 里淘汰冷热数据混存
volatile-ttl优先淘汰快要过期的 key数据有明确生命周期的场景
allkeys-random随机淘汰访问分布均匀的场景

LFU 是 Redis 4 引入的,比 LRU 更适合有明显热点分布的场景。比如商品详情缓存,少量热门商品被频繁访问,LRU 反而可能把这些热点挤掉,LFU 就不会。

线上环境调整内存参数有个技巧:不要直接改配置文件重启,用CONFIG SET动态调整,然后CONFIG REWRITE写回配置文件。这样不会中断服务。

4.4 可视化工具与日常运维命令

命令行用熟了其实比图形界面效率高,但有个可视化工具排查问题时确实直观。Redis Desktop Manager 是最早出名的那个,不过后来转为商业版了。现在更推荐Another Redis Desktop Manager,开源免费、跨平台、支持集群和哨兵,连上去能直接看到 key 的分布和内存占用情况。

装的时候注意一点:客户端工具连接的是 Redis 的服务地址和端口,不是装 Redis 那台机器本身,需要保证网络可达、端口开放、密码正确。

日常运维我常用这几条命令:

# 实时查看 Redis 每秒执行的命令,排查问题非常有价值 redis-cli -a 密码 --no-auth-warning monitor # 查看整体信息,重点看 used_memory、connected_clients、keyspace redis-cli -a 密码 --no-auth-warning info # 只看内存相关 redis-cli -a 密码 --no-auth-warning info memory # 查看慢查询日志 redis-cli -a 密码 --no-auth-warning slowlog get 10 # 查看当前连接数 redis-cli -a 密码 --no-auth-warning client list

monitor命令在线上慎用,它会输出所有执行的命令,高 QPS 场景下自己就成了性能瓶颈。排查问题时短时间开一下,看完了立刻 Ctrl+C 退出。

慢查询日志的阈值默认是 10 毫秒,可以用CONFIG SET slowlog-log-slower-than 5000调整成 5 毫秒。生产环境我一般设成 5 到 10 毫秒,能覆盖大部分需要关注的操作。

5. 踩坑实录:安装 Redis 最常见的报错与排查

5.1 编译阶段:gcc、jemalloc、make 中断

报错一:make: cc: Command not found

原因就是没装编译器。Debian 系装build-essential,RedHat 系装Development Tools组。装完gcc --version确认一下。

报错二:fatal error: jemalloc/jemalloc.h: No such file or directory

这是最经典的报错,出现在编译deps/jemalloc的时候。绝大多数情况下是上次编译中断留下的残留文件导致的,处理方式是彻底清理再重来:

make distclean make -j$(nproc)

如果反复失败,检查一下是不是deps/jemalloc目录本身不完整,重新解压一遍源码包试试。实在不行用make MALLOC=libc绕开。

报错三:cc1: error: unrecognized command line option "-std=c11"

gcc 版本太老,典型出现在 CentOS 7 上编译 Redis 6 以上版本。升级工具链是唯一稳妥的解法。可以用 Software Collections 装新版 gcc,或者直接换一个系统版本较新的机器。

报错四:make跑到一半被 killed

这是内存不足被 OOM Killer 杀了。两种处理:加内存,或者临时加 swap。编译 Redis 单个核心大概需要 500MB 到 1GB 内存,多核并行会放大这个需求。这种情况改用make单线程编译能缓解,但时间会明显变长。

报错五:You need tcl 8.5 or newer in order to run the Redis test

这个只在跑make test时报,不影响安装。想解决就装 tcl。

5.2 启动阶段:配置不生效、端口占用、权限拒绝

问题一:改了配置文件但启动后行为没变

最常见的原因是指定了配置文件但路径写错了,Redis 直接用了内置默认配置启动,而且它不会主动告诉你。启动时一定要看日志输出,如果看到类似"使用默认配置"的提示,就是路径问题。另一个可能是重复的配置项,后面的覆盖了前面的,用grep -n 参数名 配置文件检查一下有没有重复。

问题二:Could not create server TCP listening socket *:6379: bind: Address already in use

端口被占了。先查是谁占的:

ss -lntp | grep 6379 # 或者 lsof -i:6379

如果是之前启动的 Redis 残留进程,kill掉再启动。如果是别的程序,改 Redis 端口或者停掉对方。

问题三:Permission denied写入日志或数据文件失败

目录属主不对。检查一下 Redis 运行用户和目录属主是否一致:

ls -ld /usr/local/redis/data /usr/local/redis/logs # 修正 chown -R redis:redis /usr/local/redis

用 root 启动过 Redis 之后,数据目录里的文件属主会变成 root,之后再切换成 redis 用户启动就会报这个错。这也再次说明不要用 root 启动。

问题四:systemd 显示启动失败但进程实际在跑

daemonize设成了yes,导致 Redis 自己 fork 到后台,systemd 追踪的父进程退出了,就认为服务失败。改成daemonize nosupervised systemd即可。

5.3 连接阶段:Connection refused / NOAUTH / 超时

Could not connect to Redis at 127.0.0.1:6379: Connection refused

三种可能:服务没启动、端口写错了、bind配的地址不包含你连接的地址。先systemctl status redis看进程状态,再ss -lntp | grep redis看实际监听的地址和端口。

NOAUTH Authentication required

服务端设了密码,客户端没传。加-a 密码就行。注意在脚本里不要直接把密码写在命令行,用环境变量或者配置文件更安全。

DENIED Redis is running in protected mode

这是protected-mode在起作用。当bind没配或者配的是通配地址、同时没设密码时,Redis 会拒绝来自非本机的连接。解决方式有两个:要么老老实实设密码,要么明确配置bind到内网地址。不要图省事直接把protected-mode关掉。

连接超时,一点反应都没有

大概率是防火墙。CentOS 系用firewall-cmd --list-all看规则,Debian 系用ufw status。需要放行的话:

# firewall-cmd sudo firewall-cmd --permanent --add-port=6379/tcp sudo firewall-cmd --reload # ufw sudo ufw allow from 内网网段 to any port 6379

注意:放行端口时尽量限定来源网段,别用allow 6379这种全放开的写法。

5.4 常见问题速查表

现象最可能的原因快速定位命令处理方式
make 报 cc 找不到未装编译工具链gcc --version安装 build-essential 或 Development Tools
找不到 jemalloc.h编译残留ls deps/jemallocmake distclean后重编译
make 中途被杀内存不足dmesg | tail -20加内存或加 swap,改单线程编译
启动报端口占用已有实例在跑ss -lntp | grep 6379杀掉残留进程或改端口
改配置没生效配置路径写错或项重复grep -n 参数 配置修正路径,清理重复项
systemd 状态失败但进程在跑daemonize 与 supervised 冲突journalctl -u redis -n 30改 daemonize no + supervised systemd
连接被拒绝服务未启动或 bind 不匹配ss -lntp | grep redis启动服务,调整 bind
提示 NOAUTH客户端未传密码加 -a 参数或改配置
提示 protected mode无密码且监听通配地址设密码并绑定内网地址
日志写入失败目录属主不对ls -ld 数据目录chown 成 redis 用户
从节点同步不上masterauth 缺失info replication从节点配置 masterauth
AOF 文件异常大未及时重写info persistence调整重写阈值或手动 bgrewriteaof

这张表我建议存下来,出问题的时候按顺序对照,能省下大量翻文档的时间。多数报错的根因都在这十几条里。

最后分享一个我自己的习惯:每次装完 Redis,第一件事不是急着写业务代码,而是把redis-cli info的完整输出存一份到文件里,标注好日期和版本号。这个基线文件在将来排查性能问题时价值极高——你能清楚知道正常状态下连接数是多少、内存占用是多少、命中率是多少。没有基线,所有"这个数字正常吗"的疑问都只能靠猜。

另外关于版本,我的经验是不要盲目追新,也不要长期停留在老版本。跟着官方的稳定分支走,比主线落后一到两个小版本是比较舒服的位置,既有足够的新特性,也避开了刚发布时的潜在问题。升级前一定要在测试环境把 AOF 和 RDB 文件做完整体验,从新版本回退到旧版本时持久化文件的兼容性是有坑的。

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

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

立即咨询