ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Linux下Redis源码编译安装与生产环境配置避坑指南

Linux下Redis源码编译安装与生产环境配置避坑指南

1. 装之前,先把这几件事想明白

标题叫“Linux安装redis”,但真正做过生产环境部署的人都知道,安装本身五分钟能搞定,真正拉开差距的是装之前的思路。Redis这种内存型键值数据库,安装方式、配置参数、启动方式、安全策略,每一步都直接决定它在你机器上能不能稳定跑、能不能扛住业务流量。

这篇内容适合谁?刚接触Linux服务器、准备给项目配缓存的开发者,或者已经装过Redis但想搞清楚配置细节、避免踩坑的运维新手。我会把完整的安装流程、关键参数、常见坑和排查思路都过一遍,尽量让你看完就能照着操作。

先说句实在话:不同Linux发行版、不同Redis版本、不同业务场景,安装细节会有差异。我这里以最常用的CentOS 7/8系和Ubuntu 20.04/22.04系为例,版本选择Redis 6.x/7.x稳定版。你机器上如果环境不同,原理是通用的,操作上灵活调整就行。

2. 安装方式怎么选,这是个判断题

Redis在Linux上的安装方式,主流就三种:包管理器安装、源码编译安装、Docker容器安装。没有绝对的好坏,全看你的场景。

2.1 包管理器安装:快,但版本由不得你

CentOS用yum、Ubuntu用apt,直接一条命令就能装好。优点是快、省事、自带systemd服务管理。缺点也很明显——版本往往偏旧,而且有时候莫名装出来的是阉割版。比如CentOS默认源里的redis版本可能停留在3.x,连多线程IO都没有,性能瓶颈明显,很多新特性也用不上。

如果你只是本地开发、测试功能,包管理器装一下完全够用。在生产环境,尤其是对版本有要求或者需要特定编译参数的时候,我一般不建议走这条路。还有一个坑:某些源里装出来的Redis缺少systemd集成,你想用systemctl管理还得自己写service文件,反而更麻烦。

2.2 源码编译安装:最稳,也最可控

这是我最常用的方式。从官网下载源码包,自己编译、自己安装、自己配置。好处在于:

  • 版本完全可控,Redis 7.x新特性想用就用。
  • 编译参数可定制,比如指定安装路径、开启特定优化。
  • 二进制文件在自己手里,出了问题好排查。

缺点也很直接:需要gcc等编译工具,编译要花一两分钟,对新手来说过程显得“重”。但说实话,多敲几行命令换来完全掌控权,这笔账是划算的。下面我会详细介绍这种方式。

2.3 Docker安装:隔离干净,但不是万能

Docker跑Redis最大的优势是环境隔离、部署快速、版本切换方便。测试环境临时起一个实例,docker run后面加几个参数就完事。但生产环境用Docker跑Redis,有几个问题你得想清楚:

  • 数据持久化要挂载目录,配置不好数据说没就没。
  • 网络模式要选对,不然性能有损耗。
  • 容器重启策略要设置好,不然宕机后不会自动拉起。
  • 内存监控、日志收集都比裸机部署麻烦一些。

所以我的建议是:开发测试用Docker确实香,生产环境能裸机部署就裸机部署。当然如果你公司基础设施已经全面容器化,运维体系成熟,那另当别论。

3. 源码编译安装的完整实操记录

这里我走一遍完整过程,用的环境是CentOS 7.9,Redis版本选择当前稳定版7.0.x。整个过程我会把命令、参数、为什么这么做的原因都写清楚。

3.1 第一步:装编译环境

Redis是用C语言写的,源码编译必须要有gcc编译器。另外make的时候需要用到一些基础工具,一并装上。

yum install -y gcc gcc-c++ make tcl

Ubuntu/Debian系对应的是:

apt update && apt install -y build-essential tcl

这里有个细节需要注意:某些云厂商的CentOS镜像里gcc版本特别老,编译Redis 7.x可能会报错,提示你的gcc版本过低。遇到这种情况,需要先升级gcc,或者用scl源装新版gcc,具体后面排查章节会说。

3.2 第二步:下载并解压源码包

源码包去Redis官网下载就行。我习惯先下载到/usr/local/src目录,统一管理源码包位置。

cd /usr/local/src wget https://download.redis.io/releases/redis-7.0.14.tar.gz tar xzf redis-7.0.14.tar.gz cd redis-7.0.14

下载链接里的版本号,建议先去官网查一下当前推荐的最新稳定版。别像我之前有一次想当然用了7.0.0,结果编译到一半发现有个已知bug在后续patch版本才修复,又得重新下,时间都浪费了。

3.3 第三步:编译并安装

make -j$(nproc) make install PREFIX=/usr/local/redis

第二行命令的PREFIX参数指定了Redis安装目录。如果不指定,默认会装到/usr/local/bin下面,bin文件散落在系统路径里,后续管理比较混乱。指定到独立目录,比如/usr/local/redis,所有相关文件都在这一亩三分地里,卸载也简单,整个目录删掉就行。

make -j$(nproc)中的-j参数表示并行编译,$(nproc)自动取CPU核数,编译速度快很多。在一台8核机器上,Redis编译基本一分钟出头就完事。

编译过程偶尔会报错,最常见的是jemalloc相关的问题。这是Redis的内存分配器,如果不兼容当前系统环境,需要在make时指定用libc malloc:

make MALLOC=libc -j$(nproc)

什么时候会碰到这种情况?常见于某些老版本gcc搭配新系统,或者在某些ARM架构的机器上。具体原因后面排查部分展开。

3.4 第四步:验证安装结果

/usr/local/redis/bin/redis-server --version

能输出版本号,安装就算成功了。此时Redis二进制文件在/usr/local/redis/bin/目录下,但配置文件还没准备好,Redis现在跑起来用的全是默认配置,监听127.0.0.1、无密码、不持久化——这显然不是生产环境想要的状态,下一步就是配置。

4. 配置文件的四个关键维度

Redis安装完只是起点,配置才是重头戏。我把配置文件里最关键的几个方面拆开讲,每一项都解释为什么这样配。

4.1 网络与访问控制:bind、port、protected-mode

Redis默认只监听本机回环地址127.0.0.1,也就是只有本机能连。如果你需要让其他服务器访问——比如应用服务器和Redis不在同一台机器上——必须修改bind配置:

bind 0.0.0.0

意思是监听所有网卡接口。这里必须泼一盆冷水:bind 0.0.0.0和protected-mode no组合起来,等于把Redis裸奔在公网上。如果有人扫描到你的6379端口,而Redis没有密码,恶意者可以直接读写你的缓存数据,甚至通过Redis写文件功能拿下服务器。这不是危言耸听,网上被刷的案例一抓一大把。

安全的做法是:

  • bind指定内网IP,不要用0.0.0.0。
  • requirepass设置强密码,长度不少于16位,字母+数字+特殊字符混搭。
  • 云服务器安全组、防火墙层面,只对需要的IP放行6379端口。
  • 有条件就用Redis自带ACL功能,给不同业务分配不同权限账号。

protected-mode这个参数要重点说。默认值是yes,含义是:如果Redis没有设置密码,并且没有显式bind到具体非回环地址,那么只有本机能访问。一旦你配置了bind为0.0.0.0或某个具体IP,protected-mode就会失去保护作用。所以保护模式的本质是个“保险丝”,而不是安全屏障,真正扛事的是密码和防火墙。

# 配置示例 bind 10.0.0.5 port 6379 protected-mode yes requirepass YourStrongPassword123!

4.2 持久化机制:RDB和AOF怎么选

Redis数据在内存里,一旦进程退出或者机器宕机,内存数据就没了。要恢复,必须靠持久化。Redis提供了两种持久化方式,标配是RDB和AOF同时启用,双保险。

先看RDB,全称Redis DataBase,本质是定期把内存数据全量快照到磁盘的dump.rdb文件。默认配置长这样:

save 900 1 save 300 10 save 60 10000

意思是:900秒内有1次写入就触发快照,300秒内有10次写入就触发,60秒内有10000次写入就触发。这种写法的妙处在于按频率动态调整快照节奏,避免频繁全量写盘。RDB的优点是最多丢几十秒的数据、恢复速度快;缺点是快照生成瞬间会fork子进程,内存占用短暂翻倍,而且两次快照之间的数据说丢就丢。

再看AOF,全称Append Only File,记录每一次写操作,以日志形式追加到aof文件里。默认配置:

appendonly yes appendfsync everysec

appendfsync有三个取值:

  • always:每次写操作都刷盘,不丢数据,但性能最差。
  • everysec:每秒刷一次盘,最多丢一秒数据,性能和可靠性平衡。
  • no:交给操作系统刷盘,性能最好但可能丢更多数据。

生产环境建议everysec,兼顾性能和数据安全。AOF文件会越来越大,所以需要重写策略:

auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb

意思是AOF文件比上次重写时增长超过100%,且文件至少64MB时,自动触发重写,压缩日志体积。

我用一个表格把两种持久化方式对比清楚,方便你根据业务取舍:

对比维度RDBAOF
数据恢复速度快慢
数据丢失风险较高(取决于快照频率)低(取决于fsync策略)
文件大小小大
对性能影响快照fork时较明显写日志有IO开销
适用场景缓存、可接受少量丢数据对数据一致性要求高的业务

我的建议是:默认两者都开。Redis重启时优先加载AOF,因为AOF数据更完整。如果对丢数据容忍度高、追求极致性能,可以只开RDB;如果对数据安全要求极高,可以只开AOF甚至用always刷盘,但要做好性能下降的评估。

4.3 内存与淘汰策略:maxmemory和maxmemory-policy

Redis内存不是无限大的,必须设置上限,否则内存泄漏或者数据膨胀能把整台机器撑爆。这里有个常见的错误认知:以为不设置maxmemoryRedis就用不完内存。实际上,操作系统有OOM Killer机制,进程内存超过物理内存时可能被直接杀掉。所以设置内存上限是保命动作。

maxmemory 2gb maxmemory-policy allkeys-lru

maxmemory指定最大内存,可以写成 512mb、2gb 等。maxmemory-policy指定内存达到上限后的淘汰策略,常见的有:

  • volatile-lru:从设置了过期时间的数据中,淘汰最近最少使用的。
  • allkeys-lru:从所有数据中淘汰最近最少使用的。
  • volatile-ttl:从设置了过期时间的数据中,淘汰剩余存活时间最短的。
  • volatile-random:从设置了过期时间的数据中随机淘汰。
  • allkeys-random:从所有数据中随机淘汰。
  • noeviction:不淘汰,内存满了直接拒绝写入,返回错误。

生产环境最常用的是allkeys-lru,适合缓存场景——不重要的数据优先被淘汰。如果是会话存储、分布式锁这种不能丢关键数据的场景,用noeviction更安全,宁可写入失败也不丢数据。

这里还有一个重要认知:Redis在64位系统上,maxmemory不设置时理论上可用内存接近无穷大,但这不是好事。比如你的缓存key没有设置过期时间,写入量一直增长,Redis内存就会一路飙升,直到系统swap、性能雪崩、进程被杀。我的习惯是:每台Redis实例的maxmemory设置为物理内存的60%-70%,留出余量给系统和其他进程。

4.4 日志与安全加固:logfile、slowlog、ACL

默认Redis日志是输出到stdout的,也就是说前台启动时打印在终端,用systemd或后台启动时输出到journald。要把它写到文件里:

logfile /usr/local/redis/logs/redis.log

注意日志目录要先创建,Redis不会自动建目录。有几个版本竟然DIRECTORY不存在直接启动失败,或者启动成功但日志丢失,排查起来特别闹心。后来我养成了习惯,装完Redis第一件事就是把logs目录建好。

慢查询日志也是排查问题的一把利器:

slowlog-log-lower-than 10000 slowlog-max-len 128

意思是超过10毫秒的命令都会被记录下来,最多保留128条。线上事故排查时,SLOWLOG GET一下,慢命令无所遁形。

Redis 6.0之后引入的ACL功能,颠覆了以前“一个密码走天下”的模式。可以为不同业务创建不同权限账号:

user default on nopass ~* +@all user biz_app_user on >AppUserPassword123! ~cache:* +get +set +del +expire

第一行保持默认用户超管权限(本地运维用),第二行创建一个只能操作cache:前缀key的受限账号。权限最小化原则在任何系统都适用,Redis也不例外。

5. 启动、守护与开机自启

安装配置完,就该让Redis跑起来了。启动方式有很多种,我建议使用systemd来管理,好处是开机自启、进程守护、崩溃自动拉起、日志统一管理。

5.1 编写systemd服务文件

手动创建一个/etc/systemd/system/redis.service文件,内容如下:

[Unit] Description=Redis Server After=network.target [Service] ExecStart=/usr/local/redis/bin/redis-server /usr/local/redis/conf/redis.conf ExecReload=/bin/kill -USR2 $MAINPID ExecStop=/bin/kill -SIGTERM $MAINPID Restart=on-failure RestartSec=3s User=redis Group=redis LimitNOFILE=65535 [Install] WantedBy=multi-user.target

几个参数解释一下。

  • User=redis:用专用的redis用户运行,避免用root跑服务。这是安全习惯。
  • Restart=on-failure:进程异常退出时自动重启,生产环境很关键。
  • LimitNOFILE=65535:提高文件描述符上限。高并发场景下Redis需要大量文件描述符,默认1024完全不够用。

创建完服务文件后,用systemd命令操作:

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

不出意外,Redis就以守护进程方式跑起来了,配置文件生效、开机自启、异常自动拉起。

5.2 验证服务是否正常

redis-cli -a 'YourPassword' ping

返回PONG说明服务正常。这里有个小坑:命令行里用-a传密码,会有 warning 提示密码被明文记录在shell history里。能接受,但更好的方式是设置环境变量或用交互式连接。生产环境注意别把密码留在脚本里明文内嵌,用配置文件或者Redis ACL更合适。

另外别忘了验证持久化文件和慢日志功能:

/usr/local/redis/bin/redis-cli -a 'YourPassword' info persistence /usr/local/redis/bin/redis-cli -a 'YourPassword' slowlog get 10

这两条命令输出的信息,基本能确认Redis的持久化、日志记录工作正常。

6. 性能压测与基本调优

装好不代表能打。Redis处理能力怎么样,压一下才有数。自带的redis-benchmark工具就能干这活。

6.1 跑一轮基准测试

/usr/local/redis/bin/redis-benchmark -h 127.0.0.1 -p 6379 -a 'YourPassword' -c 100 -n 100000 -t set,get,incr,lpush

参数含义:

  • -c 100:100个并发连接。
  • -n 100000:总共10万次请求。
  • -t set,get,incr,lpush:分别测试这几种命令。

一台普通云服务器(2核4G)上跑完,set/get的QPS通常能到5万-15万之间。如果结果远低于这个范围,依次排查:网络是不是有瓶颈、CPU是不是被打满、Redis是否在swap、系统参数是不是没调。

6.2 几个关键的调优参数

实际压测和线上运行中,以下参数经常需要调整:

tcp-backlog 511 timeout 300 tcp-keepalive 60 maxclients 10000
  • tcp-backlog:TCP连接队列大小,并发高时可以提高,避免连接被丢弃。
  • timeout:空闲客户端超时关闭时间,0表示不关闭。如果客户端连接池连接长期空闲,建议设300秒。
  • tcp-keepalive:TCP keepalive探测周期,及时发现死连接。
  • maxclients:最大客户端连接数,默认10000,但受系统文件描述符限制。如果报max number of clients reached,除了调大这个参数,还要同步调整系统级的ulimit -n。

操作系统的几个隐藏参数也需要顺手调了:

sysctl -w net.core.somaxconn=1024 sysctl -w vm.overcommit_memory=1 sysctl -w net.ipv4.tcp_max_syn_backlog=1024

vm.overcommit_memory=1这个很多人不理解。Redis持久化时fork子进程,需要预先申请等于当前内存大小的虚拟内存。如果系统overcommit策略过保守,fork会直接失败,导致持久化失败。设置成1就是让内核允许超额分配内存,保证fork成功。

需要把这些sysctl参数写进/etc/sysctl.conf才能永久生效:

net.core.somaxconn=1024 vm.overcommit_memory=1 net.ipv4.tcp_max_syn_backlog=1024

然后执行sysctl -p使配置立刻生效。

6.3 大key和热key的治理意识

压测做的再好,线上如果存在大key和热key,性能一样崩。

大key指的是单个key的value特别大,比如几MB甚至几十MB的字符串,或者千万级别的list、hash。操作这种key时网络传输耗时高、内存占用大,还会阻塞Redis单线程执行。排查用redis-cli --bigkeys,能按类型找出大key清单。

热key指的是某个key被超高频率访问,单台Redis节点扛不住。排查用redis-cli --hotkeys需要开启LFU策略,或者通过monitor命令临时观察。

处理方案不外乎几种:大key拆分成多个小key,热key做本地缓存或多副本。这块内容展开能写一万字,今天先把排查方法放进意识里,遇到问题知道从哪个方向查。

7. 日常排查问题实录汇总

这部分是根据我实际踩过的坑整理出来的,不敢说权威,但真实有效。

7.1 问题1:编译报错MALLOC: Jemalloc Unsupported

  • 可能原因:当前系统(尤其某些ARM架构、特定版本的gcc环境)与Redis捆绑的jemalloc版本不兼容,或者gcc版本过旧导致编译阶段宏判断错误。
  • 解决办法:使用make MALLOC=libc指定使用系统的libc malloc,辅以正常参数编译安装。
  • 二次建议:如果一直报错,先升级gcc。CentOS 7老版本自带gcc 4.8.5,阿里云源可以装devtoolset,或者用scl源装gcc 8以上版本。

提示:编译Redis 7.x,完整要求gcc版本不低于4.8.5但实际推荐gcc 8+,尤其是Arm架构上。升级gcc后再编译,绝大部分问题能解决。

7.2 问题2:Redis启动后外部访问不通

现象:本机redis-cli连得上,其他服务器连不上。

排查步骤:

  1. 确认Redis进程在监听:ss -tlnp | grep 6379
  2. 确认监听地址不是只有127.0.0.1:redis-cli -a pass info server里看tcp_port。
  3. 确认防火墙状态:firewall-cmd --list-all或iptables -L -n,把6379放行。
  4. 确认云服务器安全组策略:这个经常被忽略,安全组没放行端口,你本地防火墙配得再好也没用。
  5. 最后检查redis.conf里bind和protected-mode配置。

一次线上事故的排查顺序我印象很深:当时业务方说连不上Redis,我先检查systemd状态——正常,检查端口监听——也正常,检查防火墙——放行了,最后才发现云控制台的安全组忘了加6379端口。这类问题一般就藏在最后一步。

7.3 问题3:Redis无缘无故被持久化数据拖慢

现象:某些时刻出现应用卡顿,redis-cli执行命令延迟很高。

排查过程:

  1. redis-cli --latency观察平均和最大延迟。
  2. 查看CPU使用率,如果达到100%,大概率是RDB快照fork子进程引起。
  3. 查看RDB/AOF文件所在磁盘IO情况,磁盘IOPS被打满说明快照或AOF重写太频繁。

解决办法:

  • 拉大RDB快照触发条件,或者调整save间隔。
  • AOF重写放到业务低峰期,设置auto-aof-rewrite-min-size更大。
  • 持久化文件放独立磁盘,与系统盘分离,避免互相影响。

7.4 问题4:Redis突然大量超时,但CPU和内存都不高

这个隐蔽性很强。当时排查了半天,发现是swap问题——机器内存不足,Redis内存页被换到了磁盘上,导致所有访问Redis的操作都带上磁盘IO延迟。

排查方法:看/proc/<redis_pid>/status里的VmSwap字段,不为0就有问题。解决方向:把Redis内存上限调低,给系统留足余量,或者给机器加内存,最彻底。

7.5 问题5:AOF文件损坏导致启动失败

现象:服务器异常断电后重启,Redis直接起不来,报AOF文件校验失败。

解决办法:

redis-check-aof --fix /usr/local/redis/data/appendonly.aof

这个工具会修复损坏的AOF文件,把错误的尾部截掉。修完再启动。注意修复过程可能丢失最后几条写入记录,但这是断电场景下最好的结果。

8. 我的一些经验总结

装Redis这件事,看起来是执行几条命令,实际上是三个层面的方法论:

第一,版本和安装方式需要综合评估。生产环境建议源码编译安装,部署路径统一管理;测试环境Docker快速拉起完全没问题;包管理器安装更适合完全不追求版本和定制化的场景。选型时多花五分钟想清楚,后面运维能省五小时。

第二,配置的重点不在于“能用”,而在于“扛得住”。bind、密码、maxmemory、持久化策略、文件描述符、swap这六个维度,每一项都决定了Redis在故障场景下会怎么表现。尤其是maxmemory和持久化快照的配合,线上压测时看不出问题,流量高峰期突然就出幺蛾子。合理设置内存上限和淘汰策略不是随便填个数字,而是根据业务数据量和请求量估算出来的。

第三,排查问题的耐心和系统性。Redis出问题,先看进程在不在、端口通不通、状态正常不正常,然后看日志、看监控、看参数,最后才考虑网络、硬件、系统层面。我曾经遇到一次诡异的高延迟问题,排查了两天才确认跟所在的物理宿主机有关,是虚拟化层网络调度造成的周期抖动,并不是Redis本身的问题。所以说,定位问题的过程比自己乱猜重要得多。

最后分享一个小技巧:每次改完Redis配置,务必用redis-server --test-memory或者直接重启测试,确认配置语法没写错,防止线上改完配置结果起不来。多一份验证,少一次半夜救火。

Redis是个好工具,但工具越好用,越要对它的脾气秉性摸清楚。这篇内容把安装、配置、启动、调优、排查全流程过了一遍,希望你能少踩几个我踩过的坑。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进