MacOS Homebrew 安装 Redis 与密码/ACL 配置指南 本地起一个 Redis 玩一玩本来是个五分钟的事但真动起手来很多人会卡在几个很尴尬的地方Homebrew 装完之后redis-cli能连上可配置文件到底在哪儿密码该写在redis.conf里还是用CONFIG SET动态改改了配置文件为什么重启之后还是不生效更别说 macOS 从 Intel 换到 Apple Silicon 之后路径从/usr/local变成/opt/homebrew一堆老教程直接对不上号。这篇就把 MacOS 安装 Redis 并设置密码这件事从头到尾捋一遍从安装方式怎么选、配置文件的真实位置、密码的三种设置姿势requirepass、ACL 用户、动态 CONFIG SET一直讲到密码到底有没有真正生效该怎么验证、客户端和可视化工具怎么接、以及我踩过的那几个坑。刚接触 Redis 的新手能照着抄已经用过一段时间的同学也能在密码体系和配置持久化这两块捞到点东西。1. 在 Mac 上单独装一套 Redis到底图什么1.1 本地 Redis 解决的是哪类问题公司测试环境有 Redis线上也有为什么还要在 Mac 上装一套我自己的理由很朴素开发阶段调数据结构的时候网络往返和权限申请都是纯浪费时间。你写一个排行榜的 ZSET 逻辑想验证一下ZINCRBY的返回值和分数排序是否符合预期如果每次都要连测试环境一是慢二是你没法随便FLUSHDB三是测试环境的数据被别人塞了一堆脏东西你调出来的结果根本没有参考价值。本地这一套 Redis 的价值在于它是个完全可控的沙盒。你想验证过期策略EXPIRE、想看TTL在实际读写下的变化、想试试MULTI事务里某条命令报错之后其他命令还执不执行本地随便造数据、随便清库。而且 Redis 的数据结构String、Hash、List、Set、ZSet、Stream、Bitmap、HyperLogLog、GEO里很多命令的参数组合非常绕比如SET key value EX 60 NX这种写法和老式的SETNXEXPIRE相比原子性差别在哪本地敲一遍比看十篇文档都清楚。还有一个容易被忽略的点是延迟体感。Redis 的卖点之一就是快但这个快在本地和跨机房完全不是一个数量级。你在本地测一个批量写入的耗时是 0.2ms 还是 2ms直接决定了你要不要改设计比如把 1000 次GET换成一次MGET。这种量级的差异接远程环境是测不出来的。最后是安全问题。默认装完的 Redis 是没有密码、只监听 127.0.0.1的状态。这个状态在个人电脑上问题不大但只要你哪天因为调试需要把bind改成0.0.0.0或者把 Redis 跑在一台能被同局域网访问的机器上没有密码就等于把家门钥匙插在锁上。所以我个人的习惯是哪怕是本机开发用的 Redis也一定设密码一是养成习惯二是很多客户端尤其是各种可视化工具和框架的自动配置在没有密码的环境下行为不一致早点配上密码反而能提前暴露配置问题。注意Redis 的快和没有认证是两件独立的事。加一个requirepass带来的性能损耗在绝大多数业务场景下可以忽略不要为了省那零点几毫秒的性能去裸奔。1.2 安装方式选型Homebrew、源码编译、Docker 怎么挑Mac 上装 Redis 主流就三条路我三种都用过各有各的适用场景先给一张对比表后面再展开说为什么。安装方式上手难度版本控制配置文件位置适合谁Homebrew极低一条命令跟随 formula可指定版本/opt/homebrew/etc/redis.confApple Silicon绝大多数本地开发源码编译中等需装 Xcode 命令行工具完全自由任意版本自己指定需要特定版本或改源码Docker低如果你已经有 Docker镜像 tag 精确控制挂载卷自己指定想隔离环境、多版本共存Homebrew 是我的默认选择原因很简单它把服务管理也一起解决了。brew services start redis会帮你生成一个 LaunchAgent开机自启、后台常驻、崩溃重启都不用手写 plist。而且卸载干净brew uninstall redis走人。缺点是它给的版本是跟着 formula 走的你想回退到某个老版本会稍微麻烦一点需要走homebrew/core的历史提交或者用brew tap第三方仓库。源码编译我一般只在两种情况下用一是要在老项目上复现某个特定版本的行为差异比如 Redis 6 引入 ACL 前后权限模型的差异会直接影响你的老代码能不能跑二是要做压力测试、需要打开一些默认不开的编译选项。编译本身不复杂make一把梭但后续的服务管理、日志切割、配置文件维护全都得自己来对只想写业务代码的人来说性价比不高。Docker的价值在于一次配置到处复现。如果你同时在维护几个项目一个用 Redis 5一个用 Redis 7本机又不想装两套 brew 服务那就用 Docker 起两个容器端口分别映射 6379 和 6380互不干扰。缺点也明显Mac 上 Docker 的网络层走的是虚拟机本地开发时连接延迟和文件挂载性能都会比原生服务差一截如果你在做极限性能测试容器里的数据参考价值有限。我的建议是日常开发用 Homebrew做版本兼容测试或者需要多实例隔离时切 Docker。这条路走下来最省心。1.3 动手之前先想清楚三件事在敲命令之前花两分钟把下面三个问题想清楚后面能省掉一大堆返工。第一你要几个实例。大部分人只跑一个默认实例端口 6379。但如果你在做一个需要主从或者多租户隔离的实验就得规划端口。我一般的习惯是本地默认实例 6379实验实例 6380 起用不同的配置文件、不同的 pidfile、不同的数据目录避免互相踩。第二密码策略是什么。是所有操作都用默认用户 一个密码还是给不同应用分不同的 ACL 用户前者简单配一行requirepass就完事后者多写几行但能真正做到权限隔离比如给只读的报表服务一个只能执行read类命令的用户。Redis 6 之后 ACL 是官方一等公民非常值得花十分钟了解一下。第三数据要不要留。本地开发很多人根本不开持久化重启就清空图个干净。但如果你在做的是缓存穿透、缓存雪崩这类需要重启后再现的模拟实验就得把 RDB 或 AOF 打开否则实验没法复现。这个决定会直接影响你写不写save和appendonly这两块配置。这三件事想清楚后面的步骤就是一条直线。2. Homebrew 安装 Redis 的完整实操流程2.1 装之前先确认 Homebrew 自己的状态很多人一上来就brew install redis结果报一堆权限错误折腾半天发现是 Homebrew 本身有问题。所以第一步永远是先体检。打开终端先看架构和 Homebrew 前缀uname -m brew --prefixuname -m返回arm64说明是 Apple Silicon返回x86_64说明是 Intel或者跑在 Rosetta 里。brew --prefix在 Apple Silicon 上正常会输出/opt/homebrewIntel 上输出/usr/local。这两个值决定了你后面所有配置文件的路径必须确认清楚这也是为什么网上很多教程你照着敲会报文件不存在——它们写的是 Intel 时代的路径。接着检查 Homebrew 自身是不是健康brew doctor brew updatebrew doctor输出的警告不一定都要处理但如果它提示/opt/homebrew目录权限有问题、或者有多个 Homebrew 安装比如同时装了 Intel 版和 ARM 版那就得先解决否则后面装什么东西都别扭。brew update是为了让 formula 列表是最新的避免装到一个特别老的 Redis 版本。实操心得如果你的 Mac 上曾经装过 Intel 版 Homebrew后来又装了 ARM 版which brew和brew --prefix的指向可能不一致。用which -a brew看一下有没有两个有的情况下先在~/.zshrc里把 PATH 顺序调整干净只保留一个。2.2 一条安装命令背后发生了什么正式开始brew install redis这条命令看着简单但它实际做了这么几件事理解了这些你才知道后面该去哪儿找东西。首先Homebrew 会先检查依赖。Redis 在 macOS 上基本没有额外依赖所以一般直接下载预编译好的 bottle二进制包几秒钟就能装完。如果你的架构没有对应的 bottle它会退回源码编译这时候会依赖 Xcode Command Line Tools如果没装会先提示你装。其次装完之后文件会被分散放到几个位置这是 Homebrew 的典型布局可执行文件在$(brew --prefix)/bin下面通过符号链接暴露出来配方目录在$(brew --prefix)/opt/redis配置和数据相关的东西放在$(brew --prefix)/etc、$(brew --prefix)/var下面。装完之后你可以验证一下which redis-server which redis-cli redis-server --version redis-cli --version正常情况下会输出类似Redis server v7.x.x这样的版本号。如果which找不到说明$(brew --prefix)/bin不在你的 PATH 里需要在~/.zshrc里补上export PATH/opt/homebrew/bin:$PATH改完记得source ~/.zshrc或者开个新终端。顺便说一下版本问题。Redis 官方的版本节奏是偶数版本为稳定版6.0、6.2、7.0、7.2、7.4奇数版本多是开发版。Homebrew 上的 Redis 一般是比较新的稳定版你在写配置文件的时候要注意Redis 6 是一个分水岭它引入了 ACL 和多线程 IO配置文件里新增了不少条目。如果你的项目还在老版本上配置字段可能对不上这一点后面讲配置文件的时候会再强调。2.3 启动、停止与开机自启该怎么选装完之后有两个启动姿势差别很大一定要分清楚。姿势一交给 brew services 管理推荐日常用brew services start redis这条命令做的是生成一个 LaunchAgent plist 文件放到~/Library/LaunchAgents/下面然后用launchctl把它加载起来。好处是它会开机自动启动并且进程崩了会被拉起来。你关机再开机Redis 自己就回来了不用手动操作。对应的管理命令brew services list # 看当前所有服务状态 brew services stop redis # 停止 brew services restart redis # 重启brew services list里 Redis 那一行的状态如果是started就说明在跑。姿势二前台手动启动调试配置时用redis-server /opt/homebrew/etc/redis.conf这种方式的好处是日志直接打在终端上你改了配置想看看有没有报错一眼就能看到。而且 CtrlC 就停不会留下后台进程。缺点是终端一关服务就没了而且不会开机自启。我的习惯是刚装完、在调配置文件的时候一律用前台方式启动确认配置没问题、密码能正常生效之后再brew services start redis转成后台常驻。注意不要两种方式混用。如果你先用redis-server前台起了一个又去brew services start redis第二个会因为端口 6379 被占用而启动失败。判断端口有没有被占用用lsof -nP -iTCP:6379 -sTCP:LISTEN返回结果里有进程就说明占着了。还有一个细节值得说Homebrew 版本的 Redis 默认配置里daemonize是no。这是对的因为brew services走的是 LaunchAgent本身就是在后台跑再开 daemonize 反而会导致 launchctl 管不住进程。如果你从别处抄了一份daemonize yes的配置记得改回来。3. 配置文件详解与密码设置的核心环节3.1 配置文件到底藏在哪怎么改才不出事先解决找文件的问题。Homebrew 装完 Redis 后配置文件在$(brew --prefix)/etc/redis.confApple Silicon 上就是/opt/homebrew/etc/redis.confIntel 上是/usr/local/etc/redis.conf。你可以直接cat出来看看内容几百行看起来吓人其实真正需要动的就那么几处。改之前一定要备份cp /opt/homebrew/etc/redis.conf /opt/homebrew/etc/redis.conf.bak这个习惯非常值得养成原因很实际Redis 有个CONFIG REWRITE命令它会把运行时的配置回写到配置文件里回写的过程会重排文件结构如果你手动写的注释位置比较随意重写之后可能就乱了。有备份你至少能 diff 出来到底被改了什么。另外Homebrew 升级 Redis 的时候brew upgrade有个坑它不一定会覆盖你的 redis.conf。Homebrew 对配置文件通常采取如果已存在就保留的策略但会在旁边放一个redis.conf.default之类的新版本样例文件。所以升级完之后如果你的配置文件还是老版本的新版本引入的配置项就不会生效。建议升级之后对比一下diff /opt/homebrew/etc/redis.conf /opt/homebrew/etc/redis.conf.default当然前提是这份 default 文件存在不同版本的 Homebrew formula 处理方式略有差异没有的话就去官网对照新版本的样例配置。3.2 用 requirepass 设密码最简单也最容易踩坑的一条路设密码最直接的方式就是在配置文件里加一行requirepass YourStrongPasswordHere加完之后必须重启 Redis 才生效brew services restart redis这里就是第一个大坑Redis 没有重载配置文件这个能力。不像 Nginx 有reloadRedis 只能重启才能读取新的配置文件。你要是改完配置直接redis-cli连上去发现还是免密码状态不要怀疑人生是没重启。那不想重启怎么办用动态方式redis-cli 127.0.0.1:6379 CONFIG SET requirepass YourStrongPasswordHere OK执行完之后密码立刻生效。但是CONFIG SET只改运行时内存里的配置重启之后就没了。所以正确姿势是两步走先CONFIG SET立刻生效再CONFIG REWRITE把当前运行时配置写回配置文件127.0.0.1:6379 CONFIG SET requirepass YourStrongPasswordHere OK 127.0.0.1:6379 CONFIG REWRITE OKCONFIG REWRITE有个前提Redis 必须是用配置文件启动的。如果你是不带参数直接redis-server起的或者brew services启动时没传配置文件路径CONFIG REWRITE会报错(error) ERR The server is running without a config fileHomebrew 的 LaunchAgent 模板里通常带了配置文件路径所以正常用brew services start redis起的话CONFIG REWRITE是可以用的。如果不放心可以先用CONFIG GET requirepass确认一下当前是否有密码。还有一个特别容易忽略的点CONFIG SET requirepass执行之后当前这个连接的权限不会掉。也就是说你设置完密码在这个已经连上的会话里继续敲命令还是能执行。只有新建连接才会要求认证。这个特性有好有坏好处是你不会把自己锁在外面坏处是你可能误以为密码没生效其实只是老连接还在。注意密码里如果包含特殊字符比如#、空格、在配置文件里要加引号形如requirepass p#ss word。不加引号的话#后面的内容会被当成注释密码就只剩一半然后你就会遇到明明设了密码却认证失败这种灵异事件。3.3 ACL 用户体系需要权限隔离时该怎么做requirepass本质上是给default用户设密码。所有连接只要通过认证就拥有全部权限all、~*也就是能操作所有 key、执行所有命令。本地自己玩没问题但如果你想模拟真实环境里的权限隔离就该用 ACL 了。Redis 6 之后ACL 是一等公民。一个典型的用法是给不同的应用分配不同的用户。比如我有一个只读的报表服务一个可读可写的业务服务可以这么配127.0.0.1:6379 ACL SETUSER report_user on Report#2024 ~report:* read ping info OK 127.0.0.1:6379 ACL SETUSER app_user on App#2024 ~app:* get set expire del ttl incr decr OK逐段拆解一下这几行理解了才好按需改ACL SETUSER report_user—— 创建或修改一个叫report_user的用户。on—— 启用这个用户。默认新建用户是off状态不写on是连不上的这个坑我第一次就踩了。Report#2024——前缀表示这是明文密码Redis 会存成哈希。如果加的是前缀表示后面跟的是已经哈希过的密码。~report:*—— key 的访问模式这个用户只能碰以report:开头的 key。~*表示所有 key。注意默认新建用户是没有任何 key 权限的不写这一条什么都读不了。read—— 允许这一类命令。ACL 支持命令类别常用的有read、write、keyspace、fast、slow、dangerous、admin。read就是所有标记为只读的命令。ping info—— 单独再放开几个不在read类别里的命令。PING一般不在read里但健康检查要用所以要单独加。创建之后可以查看127.0.0.1:6379 ACL LIST 127.0.0.1:6379 ACL GETUSER report_user 127.0.0.1:6379 ACL WHOAMIACL WHOAMI会告诉你当前连接用的是哪个用户调试的时候特别有用。同样ACL 用户默认也是存在内存里的重启就没了。要持久化有两条路第一条用CONFIG REWRITE。它会把你通过ACL SETUSER创建的用户以user ...的形式写进redis.conf。这也是 Homebrew 场景下最省事的做法。第二条用独立的 ACL 文件。在redis.conf里加一行aclfile /opt/homebrew/etc/users.acl之后用ACL SAVE把用户写到这个文件用ACL LOAD从文件读。这种方式的好处是权限配置和主配置分离改权限不用碰主配置团队协作时也更容易做 diff。127.0.0.1:6379 ACL SAVE OK注意如果没配aclfileACL SAVE会报错大意是本实例没有配置 ACL 文件。同时要注意requirepass和aclfile混用会让人困惑——因为requirepass实际上就是在改default用户的密码而aclfile里可能也定义了default用户谁生效取决于加载顺序。我个人的建议是用了 ACL 文件就统一在文件里定义所有用户包括 default不要再去动requirepass。3.4 比密码更重要的几条安全基线设了密码不等于安全还有几个配置项必须一起看一眼。它们就在同一个redis.conf里配置项默认值建议值说明bind127.0.0.1 -::1保持默认只监听本机回环最安全protected-modeyes保持yes无密码且非本机访问时直接拒绝port6379保持或改改了记得同步客户端配置timeout0300空闲连接自动断开避免连接泄漏tcp-keepalive300保持默认探测死连接maxmemory0不限按需设置见下文的容量计算关于bind默认的127.0.0.1 -::1意味着只有本机能连。如果你确实需要局域网内其他机器访问改成bind 0.0.0.0或者指定网卡 IP但这时候密码就是底线绝不能省。而且还要顺带检查一下 macOS 的防火墙设置否则可能连不上还找不到原因。关于protected-mode它是个兜底保护。当 Redis 检测到没有密码 绑定了非回环地址这个组合时会直接拒绝外部连接并返回一段提示。很多人以为这是 bug其实是保护机制在起作用。不要为了图省事把它关掉正确的做法是把密码配上。关于timeout本地开发设成300秒比较合适。默认的0表示永不超时如果你写了个脚本忘了关连接日积月累会把maxclients耗完。虽然本地不太可能但养成习惯是好事。关于maxmemory默认0表示不限制理论上能吃光你所有内存。本地开发一般不会撑爆但如果你在做大批量写入的测试还是要设一下。我一般的算法是留出系统和其他应用的内存给 Redis 分配物理内存的 50% 到 70%。举个具体例子16GB 内存的 Mac系统本身加上浏览器、IDE 通常吃掉 6 到 8GB那 Redis 设4gb到6gb是安全区间。设置方式maxmemory 4gb maxmemory-policy allkeys-lrumaxmemory-policy决定内存满了之后怎么淘汰。allkeys-lru是淘汰最久未使用的 key适合纯缓存场景如果 Redis 里还存着不能丢的数据比如你本地在模拟队列那就用volatile-lru只淘汰设置了过期时间的 key。4. 验证密码是否真的生效4.1 redis-cli 的几种连接姿势配完密码最要紧的是确认它真的生效了。别猜直接测。先不加密码连一下redis-cli 127.0.0.1:6379 PING (error) NOAUTH Authentication required.看到NOAUTH就说明密码确实生效了。如果返回PONG那说明密码没配上回去检查是不是漏了重启或者密码那一行被注释掉了。然后带密码连redis-cli -h 127.0.0.1 -p 6379 -a YourStrongPasswordHere如果你在输出里看到这么一行警告Warning: Using a password with -a or -u option on the command line interface may not be safe.那是正常的Redis 在提醒你命令行参数会出现在 shell 历史和进程列表里别人ps aux一下就能看到你的密码。虽然本机开发无所谓但有个更优雅的做法——用环境变量export REDISCLI_AUTHYourStrongPasswordHere redis-cli 127.0.0.1:6379 PING PONGREDISCLI_AUTH是redis-cli专门支持的环境变量设了之后就不用每次带-a也不会在命令历史里留密码。这个技巧我用了很多年强烈推荐。还有一种交互式的方式先连上去再认证redis-cli 127.0.0.1:6379 AUTH YourStrongPasswordHere OK 127.0.0.1:6379 PING PONG这种方式适合你在连上之后才想起来要认证的场景。4.2 客户端和可视化工具怎么接验证完命令行接下来把常用客户端配一遍。不同技术栈的配置位置不一样但核心就三个值host、port、password。Java / Spring Bootspring: data: redis: host: 127.0.0.1 port: 6379 password: YourStrongPasswordHere database: 0 timeout: 3000ms这里插一句关于序列化的话因为很多人加了密码之后会撞上另一个问题连上了但 key 在 Redis 里看起来是一串乱码。这跟密码没关系是RedisTemplate的序列化器没配。默认的JdkSerializationRedisSerializer会把 key 和 value 都序列化成二进制用redis-cli看到的就是一堆\xac\xed开头的乱码。建议把 key 的序列化器换成StringRedisSerializervalue 按需选 Jackson 或者其他。密码配对了但看不到数据八成是这个原因别去怀疑密码。Node.js / ioredisconst Redis require(ioredis); const client new Redis({ host: 127.0.0.1, port: 6379, password: YourStrongPasswordHere, });Python / redis-pyimport redis r redis.Redis(host127.0.0.1, port6379, passwordYourStrongPasswordHere, decode_responsesTrue) print(r.ping())可视化工具我平时主要用两个。一个是官方的 RedisInsight免费能看 key 的树状结构、能做内存分析、还能跑内置的性能测试功能最全。另一个是 Another Redis Desktop Manager轻量、启动快日常查 key 足够用界面也更简单。连接配置就四个字段名称随便写地址127.0.0.1端口6379密码填你设的那个。有一点要注意很多可视化工具在建连接的时候会做一次测试连接如果密码填错了测试会失败。但如果工具本身缓存了连接你改了密码之后它可能还在用老连接看起来像是密码改了但工具还能连。遇到这种灵异现象把连接删了重建比重启工具还快。4.3 改了密码之后怎么让所有地方都跟上密码这东西一旦改了最容易出问题的不是 Redis 本身而是散落在各处的客户端配置。我自己踩过的坑是这样的本地改了 Redis 密码项目能跑但单元测试挂了因为测试用的是application-test.yml里面还是老密码过两天 CI 也挂了因为 CI 从环境变量读密码而我没更新那条环境变量。所以改密码的时候我现在的流程是固定的先CONFIG SET requirepass 新密码让它立刻生效这时候老连接不断。用redis-cli新开一个连接验证新密码能通、老密码不通。CONFIG REWRITE把新密码写进配置文件确认文件里那一行确实变了。逐个更新客户端配置主配置、测试配置、环境变量、可视化工具、脚本里的常量。全量重启一遍相关服务确认没有遗漏的地方。第 2 步特别重要。因为CONFIG SET之后老连接还能用你很容易误判。一定要新开一个连接测试才能确认新密码真的生效了。注意CONFIG REWRITE会重排配置文件的格式。如果你在redis.conf里手写了很多注释建议先diff一下确认没被弄乱或者干脆维护一份自己的配置模板需要时覆盖过去。5. 常见问题与排查技巧实录5.1 启动失败、端口占用这些高频问题问题brew services start redis之后状态是error或者一直是started但连不上。先去日志里找答案。Homebrew 版本的 Redis 日志通常在$(brew --prefix)/var/log/redis.log tail -n 50 $(brew --prefix)/var/log/redis.log日志里最常见的几类报错第一类是端口被占用报错大意是Could not create server TCP listening socket。这时候用lsof -nP -iTCP:6379 -sTCP:LISTEN找到占用进程要么杀掉要么改 Redis 端口。我自己就遇到过因为之前前台启动的 Redis 忘了关导致服务起不来的情况。第二类是配置文件语法错误报错会带上行号和大致原因。这种一般是手改配置的时候多打了空格、漏了引号或者把某一行前面的注释符号去掉了。Redis 对配置格式其实挺宽容但字符串类型的值如果含特殊字符不加引号就会出问题。第三类是数据目录权限问题。如果dir指向的目录不存在或者当前用户没权限写Redis 启动时会报无法写入 RDB 文件的错。Homebrew 默认的数据目录一般是$(brew --prefix)/var/db/redis正常情况下权限是对的但如果你手动改过dir就要确认一下。问题改了redis.conf但不生效。九成九是没重启。再强调一遍Redis 不读配置文件的热更新CONFIG SET是唯一的热改方式但它改的是内存。改文件必须重启。问题前台启动正常brew services启动就报错。大概率是两种启动方式用的配置文件不一样。brew services走的是 LaunchAgent plist 里写死的路径你可以直接看这个文件cat ~/Library/LaunchAgents/homebrew.mxcl.redis.plist里面的ProgramArguments数组会明确写出来它用什么命令、加载哪个配置文件。对比一下你手动敲的命令差异就找到了。5.2 密码相关的问题排查表密码这块的问题最集中我整理成一张表遇到问题直接对照。现象可能原因排查方法解决方式PING返回PONG不需要密码配置没生效或没重启CONFIG GET requirepass重启服务或CONFIG SETCONFIG REWRITE带密码连接报WRONGPASS密码字符被截断检查配置里有没有#、空格没加引号密码加双引号重启设完密码后老连接还能用CONFIG SET不影响现有连接新开一个连接测试属于正常行为不是 bugCONFIG REWRITE报无配置文件启动时没加载配置文件INFO server看config_file字段用brew services重启或手动带路径启动密码正确但客户端连不上客户端缓存了老连接客户端日志里的认证错误清空连接池、重建连接ACL SAVE报错没配aclfileCONFIG GET aclfile配aclfile或改用CONFIG REWRITEACL 用户建了但连不上忘了写onACL LIST看用户状态加on重新设置ACL 用户能连但读不到 key没配 key 模式ACL GETUSER 用户名看keys字段加~前缀:*或~*INFO server是一个很好用的排查入口它会输出一大堆服务端信息其中config_file字段明确告诉你当前实例加载的是哪个配置文件。当你怀疑我改的这个文件到底是不是它在用的那个时这一条命令就够了redis-cli -a 密码 INFO server | grep config_file不对等等如果密码有问题这条命令本身就会失败所以可以先用--no-auth-warning配合环境变量REDISCLI_AUTH密码 redis-cli INFO server | grep config_file5.3 几条我踩出来的经验第一条永远不要在配置文件里写弱密码。127.0.0.1 看起来是安全的但你要知道很多恶意扫描程序会尝试扫描本机端口一旦你某天为了调试把bind改成了0.0.0.0又忘了改回来弱密码就是灾难。我一般用openssl rand -base64 24生成随机密码本地开发用的时候存到密码管理器里。第二条把密码放到环境变量里别硬编码。哪怕是本地项目也养成用环境变量的习惯。Spring Boot 里可以写password: ${REDIS_PASSWORD}Node 里用process.env.REDIS_PASSWORD。这样你的代码仓库里就不会有一份密码将来真要做代码审查或者分享 demo 的时候也不用临时去删敏感信息。第三条requirepass和ACL不要混着用。前面提过一次这里再强调。因为requirepass就是给default用户设密码如果你同时又用aclfile定义了default用户两处配置谁生效很容易搞混。选一条路走到底别脚踏两条船。第四条密码改了之后一定要检查连接池配置。应用侧的连接池比如 Lettuce、Jedis 或者各种语言的客户端通常有自己的重连策略。密码改了之后老连接可能还能撑一段时间池子里的新连接才会失败。表现出来就是改了密码之后应用看起来正常过了十几分钟开始疯狂报错。所以改密码之后主动重启一次应用比等它自己出问题要好。第五条CONFIG GET是排查万金油。任何我明明配了为什么不生效的问题第一步永远是CONFIG GET 配置项名看看运行时到底是什么值。它告诉你的是 Redis现在正在用的值而不是文件里写的值。这两者不一致就说明是热更新和持久化的同步问题。5.4 顺手解决几个日常小麻烦既然聊到排查顺便把几个日常高频的小需求也说一下都是我自己经常用的。看当前 Redis 里有多少 key、占多少内存REDISCLI_AUTH密码 redis-cli INFO memory | grep used_memory_human REDISCLI_AUTH密码 redis-cli DBSIZEDBSIZE返回当前库的 key 数量。注意不要在生产环境用KEYS *那是线性扫描会把 Redis 卡住。本地开发无所谓但习惯要养好用SCAN代替REDISCLI_AUTH密码 redis-cli --scan --pattern user:* | head -20看慢查询slowlog-log-slower-than 10000 slowlog-max-len 128slowlog-log-slower-than的单位是微秒10000就是 10 毫秒。也就是说执行超过 10ms 的命令会被记录。本地开发定这个阈值挺合适因为本地几乎没有网络延迟超过 10ms 基本就是命令本身有问题比如对大集合执行SMEMBERS。查记录REDISCLI_AUTH密码 redis-cli SLOWLOG GET 10看实时命令流调试的时候特别有用REDISCLI_AUTH密码 redis-cli MONITOR它会打印出所有被执行到的命令。排查到底是谁在偷偷写这个 key的时候这是终极武器。缺点是开销不小本地开发随便用线上千万别开着不管。简单压一下性能看看你的机器什么水平REDISCLI_AUTH密码 redis-cli -h 127.0.0.1 -p 6379 --latency redis-benchmark -h 127.0.0.1 -p 6379 -a 密码 -n 10000 -q--latency会持续采样延迟,之间的数字是平均值max是最大值。redis-benchmark会跑一套标准测试输出各命令的每秒处理量。Apple Silicon 上的本地 Redis单机 QPS 跑到几万是很轻松的如果测出来只有几百那多半是配置有问题或者机器在跑别的大任务。6. 数据要不要留持久化、备份与卸载6.1 RDB 和 AOF 怎么选前面留了个尾巴这里补上。本地开发要不要开持久化取决于你在测什么。RDB是快照模式按时间间隔把内存数据 dump 成二进制文件。配置长这样save 3600 1 300 100 60 10000 dbfilename dump.rdb dir /opt/homebrew/var/db/redissave后面跟的是秒数 变更次数的配对意思是在 3600 秒内有 1 个 key 变化、在 300 秒内有 100 个 key 变化、在 60 秒内有 10000 个 key 变化满足任意一条就触发快照。RDB 的优点是文件小、恢复快缺点是两次快照之间宕机这段时间的数据就丢了。AOF是追加日志模式把每一条写命令都追加到日志文件里appendonly yes appendfsync everysecappendfsync有三个值always每条命令都刷盘最安全但最慢、everysec每秒刷一次兼顾安全和性能推荐、no交给操作系统最快但可能丢较多数据。我的建议是本地开发如果只是跑缓存逻辑干脆两个都关掉重启即清空环境干净。如果你在做需要复现的实验比如模拟缓存雪崩、验证过期策略在重启后的行为开 AOF 加everysec就够了比 RDB 更不容易丢数据而且 AOF 文件是文本可读的出了问题你能直接打开看命令历史调试体验好得多。6.2 数据目录和备份不管开不开持久化知道数据存在哪儿总是有用的ls -lh $(brew --prefix)/var/db/redis/正常情况下你能看到dump.rdb或者appendonly.aof新版本 AOF 是放在appendonlydir目录里的一组文件。想临时备份一下直接cp走就行cp $(brew --prefix)/var/db/redis/dump.rdb ~/Desktop/redis-backup-$(date %Y%m%d).rdb或者用命令触发一次保存更稳妥REDISCLI_AUTH密码 redis-cli BGSAVEBGSAVE会在后台 fork 一个子进程做快照不阻塞主线程。执行完INFO persistence能看到最后一次保存的状态和时间。注意BGSAVE涉及 fork会有一瞬间的内存开销写时复制。本地数据量小无所谓但如果你的 Redis 里塞了几个 G 的数据fork 的瞬间内存压力会很明显别在机器已经很卡的时候做这件事。6.3 干净卸载别留垃圾玩够了想清掉步骤要完整不然会留下 LaunchAgent 和残留文件。brew services stop redis brew uninstall redis rm -f ~/Library/LaunchAgents/homebrew.mxcl.redis.plist配置文件和数据目录Homebrew 一般不会自动删因为怕误删你的数据rm -f /opt/homebrew/etc/redis.conf rm -rf /opt/homebrew/var/db/redis rm -f /opt/homebrew/var/log/redis.log哪一步该不该删你自己判断。想留个配置模板下次用就只删数据目录。7. 我自己在实际操作中的几点体会这套流程我在几台不同的 Mac 上重复过很多次从 Intel 时代的/usr/local/etc/redis.conf到现在的/opt/homebrew/etc/redis.conf中间踩过的坑基本都写在上面的表格和注意事项里了。如果只让我挑三条最重要的我会挑这三条。第一条是先确认 Homebrew 前缀再动手。所有路径都和brew --prefix绑定用它拼出来的路径永远不会错。我现在的习惯是先在.zshrc里加一行export BREW_PREFIX$(brew --prefix)以后写脚本、看配置都用$BREW_PREFIX/etc/redis.conf换机器不用改任何东西。第二条是密码这件事配置文件是主、CONFIG SET是辅。刚上手的时候我喜欢用CONFIG SET图快但很快就会发现重启之后一切归零然后你要重新回忆当初设了什么。正确的顺序永远是改文件或者CONFIG SET之后立刻CONFIG REWRITE重启新连接验证。走完这三步密码就不会再出幺蛾子。第三条是验证要新开连接。这是我在密码这件事上唯一真正栽过的坑。设完密码在当前会话里敲PING还是返回PONG我一度以为设置失败了反复折腾了半天。后来才明白 Redis 不会踢掉已经认证过的连接。从那以后我验证密码一律新开一个终端或者干脆用redis-cli加--no-auth-warning起新进程。最后分享一个我用来一键确认状态的小函数丢进~/.zshrc里敲rstat就能看到当前 Redis 的版本、配置文件路径、有无密码、key 数量和总内存rstat() { REDISCLI_AUTH${REDIS_PASSWORD} redis-cli INFO server 2/dev/null | grep -E redis_version|config_file REDISCLI_AUTH${REDIS_PASSWORD} redis-cli INFO memory 2/dev/null | grep used_memory_human REDISCLI_AUTH${REDIS_PASSWORD} redis-cli DBSIZE 2/dev/null }前提是REDIS_PASSWORD这个环境变量已经设好了。每次我在新机器上配完 Redis第一件事就是跑一下这个三行输出确认无误就可以开始写代码了。要是哪天你发现输出里config_file是空的别犹豫大概率是服务启动的时候没带配置文件回去看 LaunchAgent 的 plist 就行。这个内容后面还可以再扩比如多实例并存时怎么做端口规划和资源隔离或者把 Redis 配置纳入 dotfiles 仓库统一管理都挺值得单独写一篇的。