☰
Windows 下编译 Redis 6.0:MSYS2+MinGW 完整实践
2026/10/15 5:11:07 网站建设 项目流程

先说一个背景:很多网上教程写的“Windows下安装Redis”,其实就是下载一份现成的压缩包解压,跑一个redis-server.exe。但一到 Redis 6.0 这个版本就尴尬了——官方压根没出 Windows 安装包,网上能找到的 Windows 版基本停留在 3.x、4.x,甚至是 5.0 的移植分支。如果你因为工作环境限制,必须在一台 Windows 机器上把 Redis 6.0 编译出来跑起来,这篇文章就是给你准备的。

我这次选择的是 MSYS2 + MinGW 工具链的源码编译路线。不是 WSL,不是 Docker,而是真正在 Windows 上编译出原生可执行文件,最后把redis-server.exe和redis-cli.exe单独拷出来用。整个过程踩了一堆坑:jemalloc 编译失败、动态链接库缺失、配置文件从 Linux 服务器直接拷过来导致的启动崩溃、官方 6.0 源码根本没有--service-install参数……这里我把完整过程整理成文,希望能帮你省下至少一整天的试错时间。

1. 绕不开的现实:Windows上跑Redis 6.0的三条路径与我的选择

先回答一个最基础的问题:为什么 Redis 官方这么多年一直对 Windows 装作看不见?核心原因有两个:一个是 Redis 依赖fork(2)系统调用来做持久化,而 Windows 的进程模型和 Linux 完全不同,没有等价的 fork 语义;另一个是 Windows 下的内存分配、IO 多路复用模型(epoll)也有差异,官方不想维护两套核心。这个不做评价,但现实结果就是:想要在 Windows 上跑高版本 Redis,只能自己想办法。

针对“Windows 上跑 Redis 6.0”这件事,市面上有三条主流路径,我全部对比过:

方案获取难度版本新鲜度是否原生 Windows 进程适合场景
WSL2 里安装 Redis低跟随 Linux 发行版,一般能装到 6.x/7.x否,跑在虚拟机里开发调试、个人学习最省事
社区维护的 Windows 移植版低大多停在 5.0.x 甚至 3.2是快速临时使用
MSYS2 / MinGW 源码编译中高自己拉源码,想要哪个版本都行是,但依赖少量 DLL本文主题,有定制需求时选择

我的场景比较特殊:公司测试服务器是内网 Windows 机器,不允许装 WSL2(虚拟化层被安全策略禁用),Docker 也指望不上,但又必须复现 Redis 6.0 的某些行为和性能指标。所以只能走第三条路,把官方源码拉到 Windows 上用 GCC 交叉编译出一套可执行文件。

这里我还得说一个容易混淆的概念:MSYS2 不是一台虚拟机,它是一个运行在 Windows 上的软件发行环境,提供一套基于 Linux 风格的 shell、包管理工具pacman和编译工具链。关键在于它分为两种终端:MSYS2 Shell 和 MinGW64 Shell。前者生成的程序会依赖 MSYS2 的运行时库,后者生成的程序更接近真正的 Windows 原生程序。我选的是 MinGW64 终端,最终产出的 exe 运行时只需要把 MinGW64 的 bin 目录加入 PATH 即可。

另外,我当时也考虑过直接下载某个社区移植版凑合用,但一看版本号停留在 5.0,而且和官方 6.0 在配置项、ACL 系统、模块机制上有不少差异,就觉得花两个小时编译一次源码比“移植版兜底”更靠谱。事实证明这个决定是对的,后面我会详细说怎么把编译成果固化下来,一次编译,后续版本升级也就半小时的事。

2. 编译环境搭建:MSYS2工具链与依赖清单

如果你没接触过 MSYS2,我把它的使用逻辑简化成一个类比:它就像一个“带软件源的迷你 Linux 环境”,你通过pacman命令像在 Ubuntu 上用apt一样安装 GCC、Make、各种开发库,然后在一个类 Linux 的 shell 里执行配置和编译。整个环境装好之后只占几个 GB,但足够把大多数 Linux 下的 C 项目在 Windows 上编出来。

2.1 安装 MSYS2 与核对环境

从 MSYS2 官网下载安装包,装到C:\msys64这种纯英文路径,千万别装到带空格或中文的目录,否则后期 Makefile 的路径解析会给你上眼药。装完以后打开“MSYS2 MSYS”终端,先更新核心包:

pacman -Syu

这条命令可能要执行两三轮,因为 MSYS2 的更新是分阶段的:先更新自身核心组件,然后重启终端,再更新剩余包。中途如果出现“terminate MSYS2-like processes”的提示,直接关掉终端重开,继续执行pacman -Syu直到没有新包可更。

更新完之后,换到“MSYS2 MinGW64”终端,验证编译链:

gcc --version make --version

如果提示找不到命令,说明还没安装编译链,继续往下看。

2.2 需要安装的包

我整理了一份精简的包清单,都是 Redis 6.0 编译过程中的实际依赖:

pacman -S --needed base-devel \ mingw-w64-x86_64-gcc \ mingw-w64-x86_64-pkg-config \ mingw-w64-x86_64-xxd

各个包的作用我简单说一下,方便你判断哪些能砍:

  • base-devel:包含 GNU Make、autoconf、automake 等基础构建工具,基本必备。
  • mingw-w64-x86_64-gcc:真正的 MinGW 编译器,负责生成 Windows 原生 exe。
  • mingw-w64-x86_64-pkg-config:编译时用来查找依赖库路径的工具,Redis 的一些依赖会用到。
  • mingw-w64-x86_64-xxd:这个很多人会漏掉。Redis 编译过程中某个脚本会调用xxd命令把十六进制数据转成 C 头文件,系统里没有的话,make会在中途直接报make: xxd: Command not found,你根本反应不过来是哪里缺的。

还有几个包可以不装,但强烈建议装,后面调试会省心很多:

pacman -S --needed mingw-w64-x86_64-gdb mingw-w64-x86_64-htop

不需要装 hiredis、linenoise 这些,因为 Redis 源码自带的deps目录里就有它们的完整源码,编译时会自动跟着一起编。

2.3 获取 Redis 6.0 源码

在 MinGW64 终端里,进入你打算放源码的目录。我习惯把源码放在D:\work下,MSYS2 里对应的路径是/d/work:

cd /d/work wget https://download.redis.io/releases/redis-6.0.20.tar.gz tar -xzf redis-6.0.20.tar.gz cd redis-6.0.20

这里有一个非常重要的细节:如果你是用git clone拉下来的仓库,编译前必须先执行一条命令:

git submodule update --init --recursive

因为 Redis 源码仓库里的deps/hiredis、deps/linenoise、deps/lua都是通过 git submodule 引入的子模块。不拉子模块的话,编译过程会出现一堆“找不到头文件”的诡异报错。而下载官方 tar.gz 压缩包则没有这个问题,源码里已经打包好了所有子模块。我建议直接用 tar.gz,省事。

下载完以后,可以先看一眼源码结构里最关键的几个目录:

  • src/:Redis 核心源码,编译产物也在这里。
  • deps/:内置第三方依赖,hiredis(C 客户端)、linenoise(命令行编辑)、lua(脚本引擎)、jemalloc(内存分配器)都在这里。
  • redis.conf:默认配置文件,后面需要复制出来改。

环境到此就算齐了。接下来进入真正的重头戏——编译。

3. 从源码到可执行文件:Redis 6.0的完整编译过程

很多第一次在 Windows 下编译 Redis 的人,以为执行一条make就完事了。实际上,直接在源码根目录跑make,大概率会在deps/jemalloc这一步卡住,白白浪费时间。我先带你走一遍我最终验证能跑通的正确流程,再解释每一步背后的原因。

3.1 正确的编译命令

cd /d/work/redis-6.0.20 make distclean make MALLOC=libc -j4

先解释make distclean:如果你之前编译过猜的配置或失败的配置,它会清掉所有残留的.o目标文件和配置缓存,保证这次编译是从干净状态开始的。换编译器、换 MALLOC 方案之前都必须先执行它。

-j4是并行编译参数,数字根据你的 CPU 核心数来。内存不太够的机器建议-j2,不然容易在链接阶段把机器拖死。

3.2 为什么第一个坑是 jemalloc,以及 MALLOC=libc 的含义

Redis 在 Linux 下默认使用 jemalloc 作为内存分配器,编译时会自动进入deps/jemalloc目录执行它的configure脚本。这个脚本在 Linux 下没有问题,但在 MinGW64 环境下经常出现两类失败:

  • configure阶段报error: C compiler cannot create executables
  • 编译阶段报与pthread_atfork、malloc_stats_print相关的符号找不到

为什么会这样?因为 jemalloc 本身对平台的检测非常严格,MinGW 这套环境在它眼里属于“半生不熟”的 POSIX 环境,很多特性检测会误判或者直接编译不过。这也是网上大量 Windows 编译 Redis 教程都要加MALLOC=libc的原因——这个选项的意思是:放弃 jemalloc,使用 C 运行库自带的内存分配器。

你可能会担心:不用 jemalloc,Redis 的内存碎片率会不会更高?我个人实测下来,在开发测试场景下差异根本感知不到,除非你跑几千万级 key 匹配大量碎片场景。如果实在需要 jemalloc,也有别的路,但我不推荐新手在 Windows 下折腾,收益太低。

如果你加上了MALLOC=libc仍然在编译中途看到像下面这样的日志:

make[3]: Entering directory '/d/work/redis-6.0.20/deps/hiredis'

然后长时间卡住或者报错,先别慌。这是 Redis 在依次编译deps下的子模块,hiredis、linenoise、lua 都会依次经过编译。初次编译耗时大约 5 到 15 分钟,取决于机器性能。耐心等输出停止,只要最后回到源码根目录的命令提示符并且没有以Error结尾,一般就是过了。

3.3 编译成功的标志和产物目录

编译成功的最后几行输出大概是这样的:

CC server.o ... LINK redis-server LINK redis-cli LINK redis-benchmark LINK redis-check-aof LINK redis-check-rdb LINK redis-sentinel Hint: It's a good idea to run 'make test' ;)

看到这行 Hint,就可以确认编译链路通了。编译产物全部生成在src目录下。最关键的四个 exe:

  • redis-server.exe:服务器主程序
  • redis-cli.exe:命令行客户端
  • redis-benchmark.exe:性能测试工具
  • redis-check-aof.exe/redis-check-rdb.exe:数据文件修复工具

建议立刻把编译产物集中拷贝到一个干净目录,比如C:\redis\bin,后续操作都在这个目录下做,而不要继续依赖整个源码目录。同时把源码根目录下的redis.conf也复制到C:\redis\下:

mkdir -p /c/redis/bin cp src/redis-server.exe src/redis-cli.exe src/redis-benchmark.exe /c/redis/bin/ cp redis.conf /c/redis/

3.4 减少运行时依赖的两个编译技巧

如果你跟我一样,需要把编译出来的 exe 拿到别的机器上跑(比如测试服务器),那C:\msys64\mingw64\bin那一堆 DLL 就成了麻烦。最简单的验证办法是,在 MinGW64 终端里执行:

ldd /c/redis/bin/redis-server.exe

你会看到类似libwinpthread-1.dll、libgcc_s_seh-1.dll、libstdc++-6.dll这样的依赖。这些 DLL 都在C:\msys64\mingw64\bin里。

要减少依赖,可以在编译时给make追加两个链接参数:

make MALLOC=libc LDFLAGS="-static-libgcc -static-libstdc++" -j4

这样能把 GCC 和 C++ 标准库静态编进 exe,最终只剩libwinpthread-1.dll一个主要依赖。想更进一步的话,源码里 Redis 的 Makefile 还支持对部分单元测试单独指定静态链接,但实际运维中没必要追求“完全零依赖”,因为目标机器上只要配置好 PATH 指定到C:\msys64\mingw64\bin,或者干脆把那一个 DLL 复制到 exe 同目录,就什么问题都没有了。

4. 编译之后的应用细节:配置、前台运行与自启动方案

编译成功只意味着“有了可执行文件”,距离“能稳定跑起来”还有一段路。下面这几个问题是 Windows 环境特有的,Linux 教程里绝对不可能告诉你。

4.1 官方6.0源码没有 --service-install 参数

这是我要专门拿出来说的一点。你搜“Windows Redis 服务”,会看到大量教程让你执行:

redis-server --service-install redis-server --service-start

但这些都是旧版 Windows 移植分支的功能,Redis 官方 6.0 源码编译出来的redis-server.exe里压根没有这个命令。你可以验证:

redis-server.exe --help

帮助信息里根本没有 service 相关的选项。硬执行--service-install会直接报“Unknown option”。这个区别极其重要,否则你会以为是自己编译出了问题,又回去折腾编译链,白白浪费时间。官方源码没有实现 Windows Service API 的注册逻辑,想要自启动,必须借助系统工具把 redis-server 包装成一个服务进程。

4.2 一个必须改的配置项:daemonize 在 Windows 下的表现

把源码目录里的redis.conf打开,你会发现很多配置都是按 Linux 思路预设的。其中有一个配置项如果不改,几乎 100% 会踩坑:

daemonize no

Linux 服务器上,出于管理习惯很多人会设成daemonize yes,让 Redis 进程以后台守护进程方式运行。但在 Windows/MinGW 环境下,这个选项一定要保持no。原因很简单:daemonize yes的底层依赖于 fork 系统调用来分离进程,而这里的 fork 是模拟出来的,实际效果经常是进程直接崩溃,或者在 tasn parent 端退出后、子进程状态极其诡异。

所以 Windows 下跑 Redis 6.0 的正确姿势就是让它老老实实待在前台运行,然后通过服务管理器或计划任务把它托管起来。同时建议在配置里显式加上:

bind 127.0.0.1 protected-mode yes

这是出于安全考虑。Redis 默认监听所有网卡,在 Windows 防火墙上如果你确认过放行规则,被外网扫描到未授权访问是非常危险的。开发环境务必绑定回环地址。

4.3 用 NSSM 把 redis-server 包装成 Windows 服务

因为官方 6.0 没有服务注册参数,我这里选择了一个专门做“普通程序包装成 Windows 服务”的小工具:NSSM。它的用法非常简单,不需要写任何代码。

先把编译产物放在固定位置,假设是C:\redis\bin\redis-server.exe,配置放在C:\redis\redis.conf。然后以管理员身份打开 CMD,执行:

nssm install Redis "C:\redis\bin\redis-server.exe" "C:\redis\redis.conf"

NSSM 会弹出一个 GUI 界面,在 Redirection 页签里把redis-server.stdout.log和redis-server.stderr.log也配置一下,这样服务崩溃时能看到日志,而不是只在 Windows 事件查看器里干瞪眼。设置完成后启动服务:

nssm start Redis

如果你看过服务管理器,你会发现在Services.msc里多了一个名叫 Redis 的服务,状态是正在运行。这个方案比“计划任务开机启动”靠谱得多,因为服务管理器会在进程意外退出时触发重启策略,而计划任务没有这种机制。

4.4 用 redis-benchmark 做一次快速冒烟测试

服务或者进程跑起来之后,别急着收工。我习惯用redis-cli和redis-benchmark各跑一遍,确认两个关键点:一是能连通,二是性能没有异常到离谱的程度。

redis-cli.exe -h 127.0.0.1 -p 6379 ping

预期返回PONG。接下来执行一个最简单的基准测试:

redis-benchmark.exe -h 127.0.0.1 -p 6379 -c 50 -n 10000

这里-c 50表示 50 个并发连接,-n 10000表示总共发 10000 个请求。在 Linux 服务器上 Redis 6.0 轻轻松松十万级 QPS,但 Windows 下别抱这个期待。我的实测数据在 2 到 4 万 QPS 左右,Windows 的网络栈、MinGW 编译的线程调度都有一定开销,这个结果是正常的。如果你测出来只有几百 QPS,那两件事:关掉 Windows Defender 对 Redis 进程目录的实时保护试试,再查一下是不是有杀毒软件在拦截。

5. 编译踩坑集锦:从高频报错到排查思路

最后把这些天碰到的报错和排查思路完整梳理一遍。我自己排错的过程几乎就是一遍遍读日志、找关键字、确认环境差异的过程,这里不直接给答案,而是把完整的判断链路分享出来。

5.1 “jemalloc编译失败”是最常见的拦路虎

报错典型长这样:

make[1]: Entering directory '/d/work/redis-6.0.20/deps/jemalloc' configure: error: C compiler cannot create executables

这个错误字面上是“C 编译器无法创建可执行文件”,但真正原因不是编译器坏了,而是 jemalloc 的 configure 脚本在检测 MinGW 环境时失败了。它可能尝试编译一个测试程序,发现缺少ar、ranlib的某些选项,或者链接器不认它的某个参数。

排查链路很简单:先确认gcc --version能正常输出,再在命令行随便写一个 hello world 编译一下确认编译器本身没问题。如果编译器没问题,十有八九就是 jemalloc 的事。此时不要花时间修 jemalloc,直接用make MALLOC=libc绕开。记住这个思路:源码编译报错,先归因,再决定是修还是绕。在 Windows 平台,绕开一个官方不支持的内存分配器,成本远低于修复它。

5.2 启动时闪退:动态链接库缺失怎么查

编译成功的 exe,双击运行或者 CMD 里执行,结果窗口一闪而过,什么日志都没有。这种属于典型的 DLL 解析失败。

排查方法是在 MinGW64 终端里执行:

ldd /c/redis/bin/redis-server.exe

ldd会列出所有依赖的 DLL,并自动标注哪些找不到。找到缺失的那个,检查是否存在于C:\msys64\mingw64\bin。如果存在,就在 Windows 的系统环境变量里把C:\msys64\mingw64\bin加到Path;如果你要把 exe 拷到其它机器,就把缺的 DLL 复制到 exe 同目录。

一个小技巧:redis-server.exe前台运行时的标准输出里会打印自适应日志,如果遇到启动闪退,用 CMD 的pause命令或者直接在 shell 里运行,保证窗口不自动关闭,才能看到到底是缺哪个库、还是配置语法错了、还是daemonize yes引发的崩溃。

5.3 make test 失败要不要紧张

源码编译最后会提示你make test,很多强迫症朋友忍不住跑一下,结果在 Windows 下一堆 FAIL,心态就崩了。

我的建议是:在 MinGW 环境下,make test可以参考但不能全信。Redis 的测试框架大量依赖 fork、信号、超时控制这些 POSIX 特性,在 Windows 模拟层下很容易误报。判断标准很简单:如果失败信息集中在spawn、fork、timeout这类字样,并且你能手动redis-server.exe正常启动、redis-cli ping返回 PONG、benchmark 能跑出合理数据,那就说明核心编译没问题。把测试重心放在实际冒烟上,不要在make test的死磕里消耗时间。

5.4 版本升级时怎么复用这套环境

这套 MSYS2 环境并不只能用一次。假设几个月后你想升级到 redis-6.0.20 的后续补丁版本,流程已经模板化:

cd /d/work wget https://download.redis.io/releases/redis-6.0.20.tar.gz tar -xzf redis-6.0.20.tar.gz cd redis-6.0.20 make distclean make MALLOC=libc -j4

整个过程不需要重装任何依赖,直接复用环境。这也是我推荐 MSYS2 而不是一次性折腾 Cygwin 的原因——MSYS2 的包管理器把依赖固化得非常好,升级源码版本完全不用动编译器。

还有一个更省事的技巧:把整个C:\msys64目录压缩备份一份。这个目录本身是可移植的,解压到新机器后重新运行一次pacman -Syu就能恢复所有工具链。对需要在多台 Windows 机器上交叉编译的人来说,这比每次现装环境快太多了。


最后说一点个人体会:Windows 下编译 Redis 6.0,难点其实不在“编译”本身,而在“跳出 Windows 惯性思维”。很多人卡住,是因为拿着 Linux 的使用习惯硬套,比如默认 jemalloc、默认后台运行、默认--service-install,结果每一步都是坑。等你把 MSYS2 环境搭好、把MALLOC=libc和前台运行这两个关键点记住,后续不管编译 Redis 6.0 还是 6.2、7.x,其实都是同一个流程,照着走一遍就行。如果只是想本地快速联调,WSL2 确实更省心,但如果你的环境限制跟我一样,希望这篇文章能帮你少走几个弯路。

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

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

立即咨询