做后端这几年,Redis基本成了标配。缓存、分布式锁、排行榜、会话共享、消息队列,哪个场景背后都能看到它的影子。很多人都用过现成的Redis环境,但真到自己从头装一次、把配置捋一遍的时候,才发现坑比想象中多。这篇是“Redis从入门到精通”系列的第一篇,我就把简介、安装和配置这件事一次讲透。
文章会覆盖Linux、Windows、Docker三种常见环境的安装方式,再把redis.conf里那些绕不开的配置项逐条拆开讲,最后附上我实际踩过的一些坑和排查经验。不管你是第一次接触Redis,还是以前只会在项目里跟着教程敲两行代码,这篇都适合静下心来看完。
1. Redis到底是什么,又厉害在哪
1.1 从“缓存需求”说起
先想一个问题:你的系统访问量上来了,数据库压力大,怎么办?
最常见的办法就是把热点数据放到内存里,读的时候先查内存,查不到再去数据库。这就是缓存。而Redis本质上就是一个基于内存的键值存储系统,它把数据存在内存里,读写速度极快。
但Redis又不只是“缓存”这么简单。它支持的数据结构非常丰富:字符串、哈希、列表、集合、有序集合,还有Bitmap、HyperLogLog、GEO、Stream这些高级类型。这意味着排行榜可以用有序集合做,去重可以用集合做,简单的消息队列可以用列表或Stream做。再加上它原生支持持久化、主从复制、哨兵、集群,所以很多场景下,Redis并不只是一个缓存,而是系统里一个独立的基础设施。
我用过很多版本的Redis,从2.8一路用到7.x。坦白说,早期版本之间的差异还不算大,但从6.0开始,引入了多线程IO、RESP3协议、ACL权限控制,到7.0引入的Function和Redis Search模块化能力,Redis的能力边界一直在扩大。如果现在要从零学习和选型,直接上7.x是没问题的。
1.2 和其他方案对比,为什么选Redis
一说内存缓存,有人会想到Memcached,觉得它更简单。Memcached确实把缓存这件事做到了极致简单:纯KV、内存分配效率高、多线程模型天然不存在IO瓶颈。但它有个致命的短板,只有字符串类型,无法做复杂数据结构;不支持持久化,重启全丢;主从复制虽然是有的,但高可用的生态远不如Redis成熟。
Redis相对Memcached来说,不是一个“更高级的缓存”,而是一个“功能更全的数据存储”。你可以在Redis上跑一个完整的抽奖活动,用集合存储用户ID,用有序集合存分数排行,用发布订阅给客户端推送实时消息。这些东西如果扔给Memcached,你得上很多额外的代码。
还有一部分人会把Redis和本地缓存(比如Caffeine、Guava Cache)比较。我的看法是:本地缓存和Redis不是二选一的关系,经常是搭配使用。本地缓存放在应用进程内,速度最快,但多个实例之间数据不一致;Redis放在应用外面,所有实例共享同一份数据,虽然多一次网络IO,但一致性有保障。实践中常见的是“两级缓存”:先查本地缓存,查不到再查Redis,再查不到才落库。
2. 安装前先想清楚的三件事
2.1 版本选型:7.x还是6.x
选定版本这件事,比很多人想象的重要。直接说结论:新项目直接用Redis 7.2及以上版本,旧项目如果跑得稳,没必要为了升级而升级。
Redis 7.0开始引入了Redis Function,把Lua脚本的能力往前推进了一大步;7.2又强化了ACL、提升了内存效率;7.4之后,Redis移除了对集群模式下脚本的处理限制,还引入了调度的新特性。另外还有一个背景大家应该知道,Redis从7.4开始修改了开源许可证。如果你的公司对license比较敏感,又希望保持纯开源,那可以关注一下Valkey这个从Redis 7.2 fork出来的分支,API完全兼容Redis,由Linux基金会托管。
我个人的建议是:学习阶段直接用最新的稳定版,体验新特性;生产环境则选择一个你已经踩过足够多坑的版本,比如7.2.x,然后把版本号锁死,后续升级走正式的变更流程。
2.2 平台选型:Linux、Windows还是Docker
这是很多新手纠结最多的问题。
生产环境基本不用纠结,99%是Linux。Windows上安装Redis的方式大多是社区维护的移植版或者旧版本,只适合本地开发调试,不适合上线。
如果你用的是Windows而且又希望环境尽量和Linux一致,我推荐两条路:一是装WSL2,在WSL里安装Linux版的Redis;二是用Docker桌面版,直接跑Redis官方镜像。这两条路都能绕开Windows移植版的种种奇怪问题。
如果在Linux服务器上,那又分为两种:一种是直接用系统的包管理器安装,比如apt install redis或者yum install redis;另一种是下载源码自己编译安装。包管理器装出来的版本通常比较旧,比如Ubuntu 22.04官方源里还是Redis 6.0.x,但胜在方便、有systemd服务脚本。源码编译则能拿到最新版,目录结构也完全可控。
2.3 三种安装方式怎么选
我画个简单的表格,大家一看就明白各场景的取舍:
| 安装方式 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| Linux包管理器 | 对版本要求不高的生产环境 | 安装快、自动注册服务 | 版本较旧 |
| Linux源码编译 | 需要指定版本、自定义编译参数 | 版本可控、路径可控 | 需要手动配置服务 |
| Docker容器 | 本地开发、测试环境、快速搭建 | 一条命令搞定、环境隔离 | 数据持久化需额外配置 |
| Windows移植版 | 纯Windows本地冒烟测试 | 下载解压即用 | 版本老、坑多 |
| WSL2 | Windows开发环境 | 和Linux一致 | 需要开启WSL |
3. Linux环境安装Redis:源码编译全流程
3.1 下载源码、编译、安装
我以目前主流的7.2.5为例,完整走一遍源码编译安装。首先需要系统里有gcc和make,一般最小化安装的服务器这两个工具可能没有。
# 先装编译工具 sudo apt update sudo apt install -y wget build-essential # 下载Redis源码 wget https://download.redis.io/releases/redis-7.2.5.tar.gz # 解压并进入目录 tar xzf redis-7.2.5.tar.gz cd redis-7.2.5 # 编译 make # 安装到指定目录,比如 /usr/local/redis sudo make install PREFIX=/usr/local/redis这里有一个很多初次接触的人会忽略的点:make之后其实已经可以在源码目录的src子目录下找到redis-server和redis-cli,直接用这两个文件就能跑起来。但我不建议这么干,因为源码目录一旦被清理或者移动,服务就废了。用make install PREFIX=...把可执行文件安装到独立目录,是更规范的做法。
安装完成后,把配置文件也拷贝过去:
sudo mkdir /etc/redis sudo cp redis.conf /etc/redis/redis.conf sudo mkdir -p /data/redis配置文件我习惯放在/etc/redis下,数据目录单独放到/data/redis,不要和安装目录混在一起,这样升级时不用迁移数据。
3.2 配置systemd服务
编译安装不会自动注册系统服务,需要手动写一个systemd单元文件。这一步很多人会漏掉,导致服务器重启后Redis没起来。正确做法如下:
创建/etc/systemd/system/redis.service:
[Unit] Description=Redis Server After=network.target [Service] Type=forking ExecStart=/usr/local/redis/bin/redis-server /etc/redis/redis.conf ExecReload=/bin/kill -s HUP $MAINPID ExecStop=/usr/local/redis/bin/redis-cli -a 你的密码 shutdown Restart=always User=redis Group=redis RuntimeDirectory=redis PIDFile=/var/run/redis/redis-server.pid [Install] WantedBy=multi-user.target其中Type=forking意味着redis-server启动后自身会转入后台运行。Redis默认的daemonize no在systemd环境下不需要改成yes,因为systemd本身就能管理前台进程。如果你在redis.conf里设置了daemonize yes,那systemd这边就要用Type=forking,两者别搞混。
还需要创建一个专用的系统用户:
sudo useradd --system --no-create-home --groups redis redis sudo chown -R redis:redis /data/redis /etc/redis/redis.conf然后启动并设置开机自启:
sudo systemctl daemon-reload sudo systemctl start redis sudo systemctl enable redis sudo systemctl status redis这里我给一个我实际踩过的坑:如果用root用户启动Redis,部分版本会直接拒绝运行,提示“Redis needs to be run under a dedicated user”。所以最好一开始就单独建用户,别图省事。
3.3 验证启动结果
服务起来之后,用redis-cli验证一下:
/usr/local/redis/bin/redis-cli ping正常情况下会返回PONG。如果配置了密码,需要加上-a参数:
/usr/local/redis/bin/redis-cli -a 你的密码 ping再看一下INFO里的几个关键指标:
/usr/local/redis/bin/redis-cli -a 你的密码 INFO | grep -E "redis_version|used_memory_human|connected_clients"redis_version能确认版本号对不对,used_memory_human能看到内存占用,connected_clients是当前连接数。我习惯把这三项作为每次部署Redis之后的“开机自检项”,不用看太多指标,先确认服务健康再说。
4. Windows环境安装Redis:三种靠谱姿势
4.1 官方不提供Windows版,那Windows用户怎么办
很多人到官网一看,下载页面根本没有Windows的安装包,立刻懵了。Redis官方确实不提供Windows版本,GitHub上确实有tporadowski维护的Windows移植版,当前停留在5.0.14.1,这不是官方出品,但也有不少人在用。
如果是纯本地学习Redis命令、测试客户端连接,用这个版本完全够用。下载release里的zip包,解压后直接运行redis-server.exe即可,默认端口6379。再开一个终端,运行redis-cli.exe就能敲命令了。
但要提醒一下:不要因为这个zip包解压即用,就把Redis的数据或者主从复制跑在上面。Windows移植版有几个历史遗留问题,比如某些命令的Fork行为异常、RDB持久化在特定场景下会卡顿、对于Lua脚本的支持不完整。本地玩一玩可以,别太当真。
4.2 WSL2才是Windows开发的正道
如果你在Windows上做开发,又希望Redis行为和生产Linux完全一致,WSL2是目前的最优解。
步骤如下:
# 在Windows PowerShell里查看WSL状态 wsl --status # 如果没有启用,先装WSL2(注意看系统提示) wsl --install # 进入Ubuntu发行版后,直接安装Redis sudo apt update sudo apt install -y redis-server # 启动服务 sudo service redis-server start用WSL2的最大好处是环境零差异,你学的、配置的、跑的命令,和Linux服务器一模一样。而且WSL2对文件系统的IO性能在过去几个版本优化了不少,本地开发跑Redis问题不大。
唯一的麻烦是WSL2默认不会自动启动服务,每次进入终端都要手动执行service redis-server start。解决办法是在~/.bashrc里加上一行启动命令,或者直接在Windows的任务计划程序里配置启动时执行的脚本。
4.3 Docker跑Redis:一条命令搞定
Docker的方式其实适合所有平台,Windows、Mac、Linux都一样。只要你装了Docker,接下来就很简单:
# 拉取并启动一个最基本的Redis容器 docker run -d --name redis-demo -p 6379:6379 redis:7.2 # 带数据持久化 docker run -d --name redis-demo -p 6379:6379 -v redis-data:/data redis:7.2 --appendonly yes # 挂载自定义配置文件(推荐这种方式) docker run -d --name redis-demo -p 6379:6379 \ -v /data/redis/conf/redis.conf:/usr/local/etc/redis/redis.conf \ -v redis-data:/data \ redis:7.2 redis-server /usr/local/etc/redis/redis.conf第二种方式要注意一点:--appendonly yes是传给容器的启动参数,也就是覆盖默认的redis-server启动命令。而如果你要挂载自定义配置文件,就得像第三种方式那样,显式指定redis-server /usr/local/etc/redis/redis.conf,否则挂载的配置文件会被忽略。
Docker方式最大的好处是干净,想删掉重来就一条命令。很多人在本机装了一堆环境,Redis、MySQL、Nginx全在系统里,时间长了版本冲突就能让人崩溃。我用Docker装了Redis、PostgreSQL、RabbitMQ这些基础设施之后,本机系统清爽了很多。
5. redis.conf配置详解:每一个值得改的项
5.1 网络、访问控制与安全
先说网络。配置文件里默认的bind 127.0.0.1,意思只允许本机访问。如果你要远程连接,必须改成bind 0.0.0.0,或者指定你服务器的内网IP。这里有个安全细节,bind 0.0.0.0意味着所有网卡都开放6379端口,如果Redis没有设置密码,等于把数据裸奔在网络上,公网环境下几分钟就会被扫描器打穿。
所以远程访问必须配合protected-mode和requirepass一起用。protected-mode在Redis 3.2之后默认打开。这个模式有个特点:如果Redis没有配置密码,也没有显式配置bind,它只允许本机的回环地址连接。一旦你设置了requirepass,protected-mode就自动退场。
我建议的安全基线是:
bind 0.0.0.0 port 6379 protected-mode yes requirepass 这里填一个足够复杂的密码还有一项容易被忽略的配置rename-command。如果你们公司有安全审计要求,可以把一些危险命令重命名或禁用掉,比如:
rename-command FLUSHALL "" rename-command DEBUG ""这会直接让FLUSHALL和DEBUG命令失效,防止误操作和恶意攻击。
5.2 持久化:RDB和AOF怎么选
Redis的数据存在内存里,但如果不做持久化,重启之后内存数据全部清空。持久化有RDB和AOF两种机制。
RDB是快照方式,按固定间隔把内存数据写进一个二进制文件,默认文件名是dump.rdb。它的优点是文件紧凑、恢复速度快;缺点是间隔期内如果宕机,这段时间的数据会丢。
AOF是追加日志方式,把每次写命令追加到一个日志文件里。它的优点是数据安全性高,最多丢1秒或者1次写操作的数据;缺点是文件体积大,恢复速度相对慢。Redis 7.0之后引入了AOF文件混合持久化功能,重写后的AOF文件里既包含RDB的二进制快照,又包含增量写命令,兼顾了体积和安全性。
我给出一个比较典型的配置组合:
appendonly yes appendfilename "appendonly.aof" appendfsync everysec auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb这里我建议把appendfsync设置为everysec,也就是每秒刷盘一次。阿里云等云厂商的默认配置也基本都这样。always模式虽然更安全,但每写一次都刷盘,性能损失很大,不适合高并发写场景。
如果你既想恢复快,又不想丢太多数据,可以把RDB和AOF都打开,Redis会优先用AOF文件恢复数据。不过说实话,以现在SSD的性能,除非你对数据丢失零容忍,否则只开AOF也够用了。
5.3 内存上限与淘汰策略
Redis不能无限占内存,得给它设一个上限。
maxmemory 256mb maxmemory-policy allkeys-lrumaxmemory就是Redis允许使用的最大内存量。注意这里指的是数据内存,不包含内存碎片、子进程写RDB时的内存等。所以实际进程的RSS内存会大于这个值。
maxmemory-policy是内存满了之后的淘汰策略,常见的几种:
| 策略 | 含义 | 适用场景 |
|---|---|---|
| noeviction | 不淘汰,直接报错 | 不能丢任何数据的场景 |
| allkeys-lru | 从所有key中按LRU淘汰 | 纯缓存场景 |
| volatile-lru | 只从设置了过期时间的key中按LRU淘汰 | 混合场景 |
| allkeys-random | 随机淘汰所有key | 不太建议,淘汰的随机性太强 |
| volatile-ttl | 淘汰即将过期的key | 依赖过期时间的场景 |
我见过不少人在生产环境用noeviction,结果缓存一满,大量写请求直接返回错误,业务方一脸懵。实际上如果是纯缓存场景,用allkeys-lru最省心;如果Redis里既存了缓存数据,又存了不能丢的业务数据,那就用volatile-lru,并且给缓存key都设置合理的过期时间。
还有一个容易被忽略的参数maxmemory-samples,默认值是5。它决定了LRU策略的采样数量,值越大淘汰结果越精确,但CPU消耗也越高。一般保持默认就行,不用动。
5.4 其他常见配置项
databases 16,Redis默认有16个逻辑数据库,编号0到15。现在业界普遍不建议在一个Redis实例里开多个库,原因和MySQL的多库一样,职责不清、运维复杂。如果真有隔离需求,更推荐开多个实例,或者使用Redis Clusters。
timeout 300,客户端空闲300秒自动断开连接。默认是0表示不超时。如果是公网连接,这个超时能帮你清理一些半开连接;如果是内网,设不设都行,我一般保留默认0。
tcp-keepalive 300,建议设置,让操作系统层定期探测连接是否还活着,对清理僵尸连接很有帮助。
6. 客户端连接与可视化工具配置
6.1 redis-cli命令行常用操作
安装了Redis之后,redis-cli是你最基本、最可靠的调试工具。
# 普通连接 redis-cli -h 127.0.0.1 -p 6379 -a 密码 # 进入交互模式 redis-cli 127.0.0.1:6379> ping PONG 127.0.0.1:6379> set name "hello" OK 127.0.0.1:6379> get name "hello" # 非交互模式直接执行命令 redis-cli -a 密码 INFO我建议认真记一遍Redis常用命令,而不只是会set/get几个。比如:
# 查看所有key(生产环境慎用,会阻塞) keys * # 用scan遍历key,不会卡服务 scan 0 match user:* count 100 # 查看key的类型和过期时间 type user:1001 ttl user:1001 # 查看当前连接数和命令统计 info clients info commandstats实际生产环境,我几乎不用keys *,因为它在key很多时会导致Redis阻塞,线上事故的常见根源之一。排查问题时请用scan。
6.2 图形化客户端:RDM和Another Redis Desktop Manager
命令行再强,有时候也想要个图形界面看看数据结构。这里提两款我用过的工具。
Redis Desktop Manager(RDM)是很经典的选择。老版本免费,新版本已经转为商业软件。如果你只用基础功能,找个旧的免费版也行,但界面偏重、启动偏慢。我个人觉得现在更好用的是Another Redis Desktop Manager(又被称为A Redis Desktop Manager),这是一款开源跨平台工具,底层用Go和Vue写的,启动速度快,界面清爽,支持Windows/Mac/Linux,而且直接支持SSH隧道连接,对云服务器的排查提供了很大便利。
另外还有几个选择:RedisInsight是Redis官方出的GUI工具,功能最全,可视化数据浏览、内存分析、慢日志查看都做得很好;RedisPlus是另一款桌面客户端,但更新较慢;如果你是后端开发并且已经在用JetBrains系列IDE,那IDEA里的Redis插件也能满足一些简单的查看需求。
配置连接时,要注意填写密码和数据库编号。默认连的是db0,如果你实际用的是db1,在RDM或者Another Redis Desktop Manager里都得手动切换。
7. 实操中常见的坑和排查套路
7.1 明明启动了,为什么连接被拒绝
这类问题在初学者里出现的频率最高,90%出在bind和protected-mode上。
你本机执行redis-cli ping没问题,换成另一台服务器连接就报Connection refused或者超时。首先确认Redis进程是不是确实在监听外网IP:
ss -tlnp | grep 6379如果显示的是127.0.0.1:6379,说明配置文件里的bind还是默认值。改成bind 0.0.0.0,并重启Redis。
第二道坎就是protected-mode yes。它的逻辑是:当Redis没有配置requirepass时,只允许本机访问,远程一律拒绝。如果你的Redis确实需要远程访问,第一种解法是设置密码;第二种是显式把protected-mode设为no。但这里我强烈建议只走“设置密码”这条路,不要关闭protected模式。
还有云服务器安全组的问题。很多人本地怎么测都通不了,最后发现是云服务器的安全组没放行6379端口。阿里云、腾讯云的服务器默认安全组都不放行非标端口,需要去控制台加一条入方向规则。
7.2 密码配置之后客户端连不上
修改requirepass之后,常见的一个问题是客户端工具里没写对密码。这个其实好办,但很多人忽略了一件事:config rewrite这个命令。
假设你现在把密码写到了配置文件里,重启后生效。但如果你直接运行了CONFIG SET requirepass newpass,这是运行时改的,不会写回配置文件。等下次重启,密码又变回旧的了。所以改配置时,要么改文件重启,要么运行时修改后用CONFIG REWRITE把配置写回文件。
redis-cli -a 旧密码 config set requirepass '新密码' redis-cli -a 新密码 config rewrite注意两条命令之间密码已经变了,要用新密码来执行config rewrite,否则会提示认证失败。
7.3 systemd重启后Redis没起来
服务能跑,但服务器一重启Redis就不见了。先检查两件事:
systemctl is-enabled redis systemctl status redis如果执行结果显示disabled,说明服务没有设置开机自启。执行systemctl enable redis即可。
另一个更隐蔽的问题是,systemd服务文件里写的是ExecStart路径不对。比如你源码编译安装到了/usr/local/redis,但服务文件还是写/usr/bin/redis-server,系统就找不到可执行文件,启动失败。解决办法是重新确认which redis-server的路径,并更新服务文件。
还有一个坑:如果你的配置里有daemonize yes,而systemd的Type=forksing没配对,systemd会认为服务启动失败直接杀掉进程。我建议systemd环境下配置里写daemonize no,服务类型用Type=simple。
7.4 连接数打满、内存碎片、慢日志
生产环境还有几个常见问题值得提前了解。maxclients限制的是最大连接数,默认10000,如果你的应用连接池配得过大或者有连接泄露,会触达上限。排查时看INFO clients里的connected_clients和blocked_clients,连接数异常高且不下降,大概率是应用层没有正确归还连接。
内存碎片率可以用INFO memory里的mem_fragmentation_ratio看。如果这个值长期大于1.5,说明内存碎片很严重。解决办法是执行CONFIG SET activedefrag yes,或者通过memory purge手动清理。不过activedefrag本身也消耗CPU,建议在低峰期开启。
最后是慢日志。Redis的SLOWLOG GET命令能拿到执行时间超过阈值的命令。我一般把阈值设为10毫秒:
slowlog-log-slower-than 10000 slowlog-max-len 128当某个命令频繁出现在慢日志里,就要认真分析是不是keys *、hgetall大哈希、或者范围查询太大导致的。这是线上性能排查的第一步。
写到这里,第一阶段的安装、基础配置和问题排查就基本覆盖了。我个人在实际操作中的体会是:Redis安装本身不难,难的是理解每个配置对运行行为的影响。很多人在本地装完能跑就以为大功告成,结果一上服务器就抓瞎。其实只要把bind、protected-mode、requirepass、maxmemory这几个配置理解透了,Redis的基础使用就已经拿下一大半。下一篇我会写Redis的数据类型和应用场景,欢迎继续看下去。