前几天帮同事排查一台测试服务器,装的CentOS 7,业务那边急着要用Redis做缓存,让我顺手给装一个。我敲下yum install redis -y,回车之后看着终端滚出一堆依赖包,同事在旁边愣了:“这么简单?”我说,简单是简单,但你要是真以为这就完事了,后面有你哭的。
yum安装Redis,表面上看确实是一条命令的事,但要装完能稳定跑、能远程连、能开机自启、能扛住业务流量,中间藏着一堆细节。我相信你在搜“yum安装redis”的时候,肯定也顺带搜过“配置yum源”“redis安装配置”“redis可视化工具”“redis分布式锁”这些词,说明你不只是想装个能跑的redis-server,你更关心装完之后怎么用、怎么管、怎么排查问题。这篇文章就是围绕这一整套流程来的,以我长期维护RHEL系服务器的经验,把yum安装Redis从选型、换源、安装、配置、安全加固,到客户端连接和进阶玩法完整走一遍。
不管你是刚接触Linux的小白,还是已经写过不少业务代码但没怎么自己搭过Redis的开发者,这篇文章都能让你少走几步弯路。我会把自己踩过的坑和日常运维里最实用的命令都放进去,你可以直接照着操作。
1. 为什么服务器上装Redis,我优先用yum而不是编译安装
1.1 yum安装和源码编译的真实差距
很多人一上来就跑去Redis官网拷贝源码包,wget下来、make、make install,折腾半小时装好一个最新版Redis,觉得自己很硬核。但真到了生产环境,我更倾向于先问问自己:这活儿用yum能不能干?
yum安装的本质是装一个由发行版维护者打包好的rpm,二进制、配置模板、systemd服务脚本、目录结构全都给你摆好了。你装上之后,systemctl start redis就能起来,/etc/redis.conf、/var/log/redis/redis.log、/var/lib/redis/这些路径全是约定俗成的,出问题去查文档、搜问答,别人给的命令你直接能用。
源码编译则意味着你要自己处理gcc、make、jemalloc这些工具链依赖,自己把二进制放到某个目录,自己写systemd服务脚本,自己建数据目录和日志目录,甚至还得自己考虑PID文件放哪。不是不能做,是维护成本高。
我整理了一个对比表,你一看就明白:
| 对比项 | yum安装 | 源码编译 |
|---|---|---|
| 安装速度 | 秒级完成,自动处理依赖 | 需要编译工具链,耗时较长 |
| 版本新旧 | 跟随发行版源,可能偏旧 | 可以装到官网最新版 |
| 服务管理 | 自带systemd脚本,开箱即用 | 需要自己写启动脚本 |
| 目录结构 | 统一规范,日志/配置/数据分开 | 自己定,容易散乱 |
| 升级维护 | yum update统一升级 | 需要重新编译,还可能丢配置 |
| 定制能力 | 低,只能装官方rpm | 可以加编译参数,定制路径 |
1.2 版本偏旧这件事,其实没那么可怕
我知道你担心的点:CentOS 7默认的redis包只有3.2版本,很多新特性没有,网上教程动不动就说“Redis 6开始支持ACL”“Redis 7引入了Function”,你想用新东西怎么办?
我的看法是,先看你的业务到底需不需要那些新特性。绝大多数项目拿Redis当缓存、存Session、做分布式锁、做简单的消息队列,用到的命令无非是SET、GET、EXPIRE、LPUSH、PUBLISH这些,这些能力Redis 3.2早就具备并且非常稳定了。你为了一个用不上的新命令去冒编译风险,不划算。
万一真的需要新版本,也不是非得源码编译。你可以启用EPEL源、Remi源,或者直接用Redis官方提供的rpm仓库,照样能用yum装到较新的版本。翻一下热搜词里“配置yum源”“更换国内yum源”出现频率那么高,说明装不上或者装得慢,多数时候不是命令不对,是源没弄好。
1.3 什么时候我才推荐源码编译
先说结论:默认情况下,我永远优先yum。但确实有几种情况我会老老实实去编译:
- 需要自定义安装目录,比如数据盘是单独的挂载点,想把整个Redis都装到指定路径下。
- 需要特定的内存分配器调优,比如针对大页内存、特定jemalloc版本有要求。
- 需要用最新的Redis版本做新特性验证,比如测试Redis Cluster的新命令、测试Redis 7的Function功能。
- 公司内部堡垒机和操作系统版本太老,老到自带的源里根本没有Redis包。
如果只是上面说的常规使用场景,别折腾,yum一台机器三分钟搞定,剩下的时间拿去看日志都比编译有意义。
2. 装之前先收拾yum源:备份、换源、验证一次到位
2.1 先看看这台机器的yum源现状
很多新手一上来就是yum install redis -y,结果卡在Could not resolve host或者下载元数据超时,心态直接崩了。这多半是yum源的问题,官方镜像站在海外,访问慢甚至不通。
动手之前,先用这几条命令摸清情况:
cat /etc/os-release uname -m yum repolistcat /etc/os-release看系统版本,uname -m看架构。这里多说一句,热搜词里出现了“aarch64 CentOS 7更换yum源”,说明用ARM架构服务器的人不少。好在国内镜像站都支持$basearch变量,替换baseurl的时候会自动匹配x86_64或aarch64,你不需要自己手动改架构名,但前提是别把repo文件里的路径写死。
yum repolist会列出当前已经启用的仓库数量。如果你的机器是刚装好的精简版系统,可能一个可用源都没有;如果之前别人配过,你会看到类似base、extras、updates这样的仓库名。
2.2 备份源文件并替换为国内源
换源的第一步永远不是删除,而是备份。鬼知道这个系统上原来配了什么内部源,万一新源不合适,你得能切回来。
mkdir -p /etc/yum.repos.d/backup mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/backup/然后把源文件删光挪光之后,创建新的repo文件。这里以阿里云源为例,CentOS 7系统的写法是这样的:
[base] name=CentOS-$releasever - Base baseurl=https://mirrors.aliyun.com/centos/$releasever/os/$basearch/ gpgcheck=1 gpgkey=https://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-$releasever [extras] name=CentOS-$releasever - Extras baseurl=https://mirrors.aliyun.com/centos/$releasever/extras/$basearch/ gpgcheck=1 gpgkey=https://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-$releasever [updates] name=CentOS-$releasever - Updates baseurl=https://mirrors.aliyun.com/centos/$releasever/updates/$basearch/ gpgcheck=1 gpgkey=https://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-$releasever如果你装的是Rocky Linux或者AlmaLinux,思路完全一样,把路径里的centos换成对应系统名就行。要是你的系统$releasever变量取不到值,比如用了某些精简过的镜像,那就直接把路径里写成大版本号,比如7,简单粗暴但很有效。
有一点要提醒:CentOS 7已经停止维护了,老的镜像站路径可能已经被移到vault目录,遇到404就改用https://mirrors.aliyun.com/centos-vault/7.x.xxxx/os/$basearch/这种vault路径。老环境还能用yum,靠的就是这招。
2.3 清理缓存并验证源是否可用
源文件配好之后,执行:
yum clean all yum makecachemakecache会把每个仓库的元数据拉下来,这个过程能直观地告诉你源通不通。如果输出里每个仓库后面都跟着一堆Memcached一样的进度条并且最终提示complete,说明源没问题了。
然后再跑一次yum repolist,确认仓库数量和你预期一致。这时候再yum install redis -y,下载速度就该是秒开的感觉了。
这里还要说一个很多人在内网环境碰到的情况:机器完全不能访问公网。这时候别想着换外网源了,老老实实做本地源。做法是找一台能联网的机器把ISO或者rpm包仓库拉下来,放到内网服务器上用createrepo生成元数据,然后repo文件里的baseurl写本地路径,比如baseurl=file:///opt/yum-repo。这是不少公司的标准化操作,也是热搜里“配置本地yum源实验目的”这类词背后的真实场景。你理解了这一层,以后碰到断网环境装Redis就不会抓瞎。
3. yum install redis落地过程:从命令到第一次返回PONG
3.1 安装命令和执行输出怎么看
源搞定之后,安装就真的是这条命令:
yum install -y redis装上之后你会看到终端刷过一堆依赖,这里最值得注意的依赖是jemalloc,Redis官方性能调优里经常提到它。发行版打包者在做rpm的时候,已经把Redis和这个内存分配器的关联处理好了,这也是我说yum省心的原因之一。
装完后用rpm -ql redis看关键文件都放哪了,你会看到这样一组非常有规律的路径:
/usr/bin/redis-server:主服务二进制/usr/bin/redis-cli:命令行客户端/etc/redis.conf:主配置文件/usr/lib/systemd/system/redis.service:systemd服务脚本/var/lib/redis/:默认数据持久化目录/var/log/redis/:日志目录
这个目录结构是不是很清爽?一个rpm把日志、数据、配置、服务脚本全分好了。源码编译你得自己手动把这些目录搭出来,哪一步忘了,后面排错都是眼泪。
验证版本用:
redis-server --version如果你在CentOS 7上看到Version 3.2.12,别慌,正常。如果你看到command not found,那说明要么源里没装到,要么rpm装完后PATH里没有。先用find / -name redis-server 2>/dev/null找一下,再用ln -s做个软链就能解决,别上来就重装系统。
3.2 三种启动方式:前台、后台、systemd
装完Redis,你可以用三种方式启动它,但适用场景完全不同。
第一种,前台启动,直接执行redis-server。日志会刷在终端里,优点是你肉眼能看到一切输出,适合验证配置有没有语法错误。缺点是窗口一关,Redis就没了。这是开发调试用的,不是生产用法。
第二种,后台启动,指定配置文件并开启daemonize:
redis-server /etc/redis.conf --daemonize yes这么做的问题在于服务不受systemd托管,重启服务器之后Redis不会自动拉起来,而且进程状态不会跟随系统会话正常管理,一旦异常退出,没有自动拉起机制。开发环境图省事可以这么玩,生产别这样干。
第三种,systemd托管启动:
systemctl start redis systemctl status redis这是我在生产环境唯一推荐的方式。systemd会帮你管好进程生命周期、开机自启、崩溃重启、资源限制。你去看/usr/lib/systemd/system/redis.service文件,会发现ExecStart和PIDFile都对应着配置清单,说明发行版打包者早就把这事安排妥了。
3.3 用redis-cli做第一次连通性测试
服务启动之后,马上验证一下它是不是真的能干活:
redis-cli ping看到PONG,说明服务起来了,端口在监听,客户端能连上。接着来一组最基础的读写:
redis-cli set hello world redis-cli get hello返回world就说明一切正常。再跑一条看一下服务整体状态:
redis-cli info这条命令输出很长,重点看这几个字段:
redis_version:确认跑的版本。uptime_in_seconds:进程启动了多长时间,验证有没有反复重启。connected_clients:当前有多少客户端连接。used_memory:Redis实际占用内存。role:当前是主节点还是从节点。
我习惯每次装完Redis都把这几个字段看一遍,不是为了装,而是跑完redis-benchmark这类压测工具之后,能通过used_memory和connected_clients对比出性能数据。顺便提一句,redis-benchmark虽然好用,但生产环境别在业务高峰乱跑,CPU瞬间被拉满的滋味谁跑谁知道。
4. redis.conf和服务管理:别让重启变成灾难
4.1 redis.conf里最值得改的几个参数
很多刚接触Redis的朋友跑通PONG之后就收工了,实际上这个状态下的配置完全不能用于生产。下面这张表列的是我每次安装都会逐项check的参数,你照着检查一遍基本不会漏:
| 参数 | 默认值 | 生产建议 | 说明 |
|---|---|---|---|
| bind | 127.0.0.1 | 127.0.0.1或内网IP | 默认只本机可访问,远程连不上先看它 |
| protected-mode | yes | yes | 保护模式,没设密码时强制限制外网访问 |
| port | 6379 | 6379或自定义 | 改端口要同步改客户端配置 |
| requirepass | 空 | 强密码 | 没设密码等于裸奔 |
| maxmemory | 0(无限制) | 物理内存的70%左右 | 不限制可能把整机内存吃光 |
| maxmemory-policy | noeviction | allkeys-lru或volatile-lru | 内存满了踢哪些key |
| save | 900 1 / 300 10 / 60 10000 | 按业务调整 | RDB快照触发条件 |
| appendonly | no | yes | 开启AOF持久化,容灾性更强 |
| appendfsync | everysec | everysec | 每秒刷盘,性能和安全的平衡点 |
| logfile | "" | /var/log/redis/redis.log | 默认日志打stdout,systemd下不容易看到 |
这里重点展开maxmemory-policy。好多人一听LRU就说“那不就是淘汰最近最少用的吗”,但要注意allkeys-lru和volatile-lru的差别:前者对所有key生效,哪怕key根本没设过期时间也会被淘汰;后者只淘汰设置了过期时间的key,没有过期时间的key被保留。如果你拿Redis做持久缓存,不希望业务key被莫名清掉,就选volatile-lru;如果它是一个纯缓存层,丢了也无所谓,选allkeys-lru省心。
4.2 用systemd管好Redis的开机自启
配置文件按需改完后,做一次自启和重启验证:
systemctl enable redis systemctl restart redis systemctl is-enabled redis返回enabled就是开机自启生效了。这一步很多教程不会教,但服务器重启后Redis没有自动拉起,第二天业务报缓存全没了,你就知道这行的价值了。
还有一个非常隐蔽的坑:redis.service里的PIDFile路径和redis.conf里的pidfile参数如果不一致,systemctl status redis会提示Supervising process which is not our child之类的段错误警告,甚至认为服务启动失败。发行版的rpm包通常把两处路径写好了,但如果你自己手改过redis.conf里的pidfile,或者从源码编译后用systemd脚本去管,就非常容易踩中。排查方法很简单,查看两个文件里的路径是否对齐:
grep -E "ExecStart|PIDFile" /usr/lib/systemd/system/redis.service grep "^pidfile" /etc/redis.conf4.3 用journalctl和ss验证运行状态
启动完成后,我用这几条命令看服务到底健不健康:
systemctl status redis journalctl -u redis --no-pager -n 50 ss -tlnp | grep 6379journalctl能直接看到systemd托管下Redis的启动日志,这比去翻日志文件省事。ss -tlnp是确认端口监听的最终手段,如果这一条没有输出,说明Redis根本没在监听,后面客户端连不上先回来查这步。
再补充一个内存相关非常容易被忽视的参数:vm.overcommit_memory。Redis在持久化fork子进程时,如果系统内存不足且overcommit策略太保守,可能直接fork失败。第一次启动时日志里通常会给你提示,把这个值设成1:
echo "vm.overcommit_memory = 1" >> /etc/sysctl.conf sysctl -p这一步不配,短时间不出事,等到内存吃紧或者触发BGSAVE的时候突然出问题,你再回头查就晚了。
5. 安全加固:密码、绑定IP和保护模式一个都不能少
5.1 protected-mode默认开启的意义
Redis的protected-mode yes到底保护了什么?简单说,当Redis没有配置bind,也没有设置requirepass时,保护模式会拒绝来自本机以外的一切访问。这是Redis团队在3.2版本之后引入的保命设计。
为什么要保命?因为以前很多人在服务器上装完Redis就是默认状态,然后直接把6379端口暴露在公网。Redis本身没有复杂的账号体系,默认不需要密码,黑客扫到开放端口后,用一条CONFIG SET dir /var/spool/cron配合CONFIG SET dbfilename root就能把恶意命令写进定时任务,拿到服务器权限。我这些年见过太多机器被植入挖矿脚本的案例,无一例外都是Redis裸奔。
所以我自己装Redis的第一步,永远是先确认protected-mode是开启状态,并且在没有配置密码的情况下,绝不把bind改成0.0.0.0。
5.2 设置密码的正确姿势
设密码的方式非常直白,在redis.conf里加一行:
requirepass 你的强密码密码怎么生成?用系统自带的随机数工具:
openssl rand -base64 32生成的字符串直接粘贴进去就行,比你自己编一个“admin123”安全得多。改完之后重启服务,再用客户端连接时就要带上密码了:
redis-cli -a '你的密码'如果不想让密码出现在命令行历史里,可以先redis-cli进入交互模式,再执行AUTH 你的密码。注意,配置了requirepass之后,所有客户端连接都必须执行AUTH,否则Redis会给你回一个NOAUTH Authentication required。
从一个老运维的角度再多说一句:密码只是第一道门。Redis 6之后支持真正的ACL访问控制,你可以在配置里创建独立用户,给不同业务分配不同命令权限和key前缀权限。比如只允许某个用户GET/SET且只能操作cache:*这个前缀。如果公司安全要求比较严,建议你后续把ACL用起来,而不是一个超级密码打天下。
5.3 从“连不上”到“连上了”的完整排查链路
到了这一步,很多人的下一个问题就变成了:我在自己电脑上拿可视化工具去连服务器的Redis,为什么总是超时?
我在服务器上排查这类问题时,按照下面这个链路一步一步走,基本十有八九能定位:
先在本机确认Redis进程和监听地址:
ss -tlnp | grep 6379如果看到127.0.0.1:6379,说明Redis只绑定了回环地址,公网或内网客户端当然连不上。要么改bind为内网IP加上密码配合,要么就用SSH隧道转发。然后确认防火墙有没有放行6379端口:
firewall-cmd --list-all看到6379不在列表里,就执行:
firewall-cmd --permanent --add-port=6379/tcp firewall-cmd --reload这一步做完,再拿你自己电脑上的工具试一次。如果还不行,先看看云厂商的控制台安全组,很多机器装完Redis连不上,是安全组压根没放行这个端口。最后一个检查点是密码,客户端连接配置里密码填错了,表现也不是一句“密码错误”,而是各种connection refused或者auth失败,容易让人误判成网络问题。
顺带说一个很多用Spring Boot踩过的坑:报错里带着redis command timed out和io.lettuce.core字样,这通常不是Redis本身的问题,而是客户端到服务器的TCP连接建立失败或者认证超时。排查思路还是上面这套,先去确认端口通不通、密码对不对、监听地址有没有问题。
6. 命令行和可视化工具:连接不上时按这条链路排查
6.1 命令行工具才是排查的根
可视化工具再方便,我也建议你先练熟命令行。redis-cli是你在服务器上排错的第一抓手,很多现象用可视化工具看不出来,用命令行一眼就懂。
几个值得记的命令:
redis-cli -a '密码' --raw--raw这个参数非常实用。默认情况下Redis返回的字符串会被双引号包起来,中文内容还可能显示成转义后的\xe4...,加上--raw按原始字节输出,看中文内容舒服很多。
生产环境里查key,我从来不用KEYS *,这个命令在大数据量下会阻塞Redis主线程,导致线上抖动。正确的姿势是用SCAN:
redis-cli --scan --pattern 'user:*'SCAN是游标式遍历,不会一次全量阻塞。同理,终端里看key的类型和过期时间也很常用:
redis-cli type user:1001 redis-cli ttl user:10016.2 可视化工具选型和连接配置
命令行是手术刀,可视化工具是仪表盘,两个都该有。这几年我用过的工具里,比较有代表性的是这三个:
| 工具名称 | 是否免费 | 适合场景 | 需要注意 |
|---|---|---|---|
| Redis Desktop Manager(RDM) | 新版收费 | 老用户习惯 | 免费版只支持老版本,商业化之后不太好用 |
| Another Redis Desktop Manager(ARDM) | 完全免费 | 日常开发调试 | 跨平台,支持SSH隧道,目前用的人最多 |
| RedisInsight | 官方免费 | 需要官方全特性支持 | 官方出品,但界面偏重,某些老版本系统跑起来稍卡 |
如果Redis只绑定了127.0.0.1,可视化工具在服务器外面是连不上的,但你可以三个方案选择一个:要么把bind改为内网IP并且设置强密码,要么开通SSH隧道转发端口,要么在服务器上用本地端口转发。我个人在开发机上的做法是:Redis绑内网IP,强密码,云安全组只放行公司出口IP到6379,这样既方便又能挡住大多数扫描流量。
还有一个很容易被忽视的细节:连接工具里填的Database默认是0。Redis默认有16个逻辑库(0到15),很多人把数据写进了db1,结果工具默认连的是db0,看到一片空白就以为Redis坏了。先SELECT 1再看一眼,这种低级误判我见过不少。
6.3 连接工具报错信息怎么看
NOAUTH Authentication required:没带密码或者密码没生效,去检查requirepass配置。DENIED Redis is running in protected mode:没设密码但保护模式生效了,绑定的还是外网地址,外部连接被拒。先设密码,再把protected-mode改为yes,问题就解决。Connection reset by peer:端口通但服务异常,多半是Redis进程崩了或者在重启,先去看日志。Connection timed out:TCP都到不了,检查安全组、防火墙、bind地址,顺序就是从本机ss一直到云平台安全组。
7. 装上只是开始:从缓存到分布式锁再到集群的进阶路径
7.1 五大数据类型别只会用String
Redis装好了,缓存也跑了,但很多人自始至终只用了SET和GET,这就太浪费了。Redis之所以叫数据结构服务器,是因为它原生支持五种核心数据结构,每种都有明确的适用场景:
| 类型 | 常用命令 | 典型场景 |
|---|---|---|
| String | SET、GET、INCR、SETNX | 计数器、缓存、分布式锁 |
| Hash | HSET、HGET、HGETALL | 存对象字段,比如用户信息 |
| List | LPUSH、RPOP、LRANGE | 简单消息队列、最新列表 |
| Set | SADD、SISMEMBER、SPOP | 去重、抽奖、共同好友 |
| ZSet | ZADD、ZRANGEBYSCORE、ZSCORE | 排行榜、延时队列 |
举个例子,一个资讯App的“今日热点排行”用ZSet实现再合适不过,score直接存点击量,ZREVRANGE key 0 9就能拿Top10。你如果只会用String,每个分类都要自己维护排序逻辑,效率差远了。
7.2 缓存治理和分布式锁的经典问题
你搜“redis分布式锁”“redis做中间件”“redis缓存治理”,本质上都是在问同一个问题:单机能跑了,怎么在业务里用得稳?
先说缓存治理。缓存穿透(查询一个不存在的key导致每次打到数据库)、缓存击穿(热点key过期瞬间大量请求打到DB)、缓存雪崩(大量key同时过期导致DB被打爆),这三个是面试高频题也是生产高频事故。应对方案很成熟:穿透用布隆过滤器或者缓存空值,击穿用互斥锁重建缓存,雪崩给过期时间加随机值。yum装的Redis一样能把这些方案全跑起来。
再说分布式锁。最常见的实现是SET key value NX EX 30,意思是只有key不存在时才设置成功,且带30秒过期。这套方案能解决“锁忘了释放”的经典问题。但要注意,生产上更稳的姿势是用Redisson这种成熟客户端,它内部处理了锁续期、看门狗、可重入这些边角逻辑,别自己从头造轮子。
7.3 单机不够用:Sentinel和Cluster方向
等你这台yum装的Redis把业务支撑起来之后,数据量大了、并发高了,自然要考虑集群方向。两条主线:一是Redis Sentinel哨兵模式,解决主从切换和高可用问题;二是Redis Cluster集群模式,解决数据分片和水平扩展问题。
另外一个很多新手会问的方向:生产环境能不能用Docker跑Redis主从?能,但要注意数据持久化卷挂载、网络模式选型、容器重启策略,这些细节处理不好的话,容器一重启数据全没。我在折腾Docker跑Redis时也踩过docker search redis报错的坑,那多半是Docker引擎侧的问题,和Redis本身关系不大,优先检查Docker服务状态。
这一轮从yum换源、装包、配置、加固到集群方向走下来,你会发现“yum install redis”本身只是一把钥匙,真正值钱的是你拿着这把钥匙把Redis稳定跑起来、和业务好好结合的能力。我运维服务器这些年,最深的体会就是:别小看任何一条“简单”的安装命令,把安装之后的事情想清楚、做扎实,才是一个工程师真正的分水岭。
最后分享一个我自己常年保留的小习惯:装完Redis之后,我会顺手写一个redis-check.sh脚本,定时检查进程存活、内存水位和日志文件异常,配合crontab每天跑一次。Redis这玩意儿本身够稳,大多数事故都出在“没人看它”上面。你把它当成一个有脾气的服务来伺候,它就能安安稳稳给你扛业务。