
1. 动手之前先搞清楚你的ARM环境和真实需求最近不少朋友在ARM设备上折腾Redis包括树莓派、香橙派这类开发板也有飞腾、鲲鹏这样的服务器平台甚至有人想在Apple Silicon的虚拟机里跑一个Redis实例。这个需求本身不复杂但ARM架构和常见的x86环境有不少细节差异照着网上那些“Ubuntu安装Redis”的教程抄作业很容易在编译环节卡住或者在启动阶段遇到莫名其妙的问题。先说清楚这篇文章要解决什么问题在ARM架构的Ubuntu系统上用两种主流方式安装Redis一种是apt直接装一种是源码编译安装同时把配置、服务化、常见坑位和性能调优一并梳理清楚。适合谁看在ARM开发板上做嵌入式开发的工程师、用ARM云服务器但没接触过编译部署的后端同学、以及因为好奇想跑一跑Redis的Linux爱好者。1.1 为什么ARM上装Redis会和x86有区别很多人在x86的Ubuntu上装Redis装惯了以为换成ARM就是换个架构、命令照敲。实际上差异是实打实的。ARM处理器分两大类一类是64位的AArch64架构指令集叫arm64常见的树莓派4/5、RK3588开发板、飞腾/鲲鹏服务器都走这个路线另一类是32位的ARMv7架构对应armhf或armel软件包像树莓派2、一些老旧安卓开发板还在用。这两种架构在Ubuntu里对应的软件源、二进制包、编译参数都不一样。Redis本身是C语言写的跨平台能力很强理论上源码在ARM上可以直接编译。但问题往往出在依赖库和内存分配器上。Redis默认使用jemalloc管理内存这个库在部分ARM环境下会出现编译告警或者行为异常需要切换成libc自带的malloc。另外Redis 6.0以后的部分特性依赖较新的GCC特性如果你手上的Ubuntu版本太旧比如16.04GCC版本偏低编译可能直接失败。还有一点容易被忽略ARM设备的性能差异极大。同样是“ARM Ubuntu”树莓派Zero的处理器和鲲鹏920的处理器完全不是一个量级。很多人没想清楚这一点在小内存设备上按服务器标准配置Redis结果启动后没跑几分钟进程就被OOM killer干掉了。所以动手之前先花两分钟确认一下自己的硬件底细能省下后面一大把排错时间。1.2 安装前建议先做的三步环境检查在运行任何安装命令之前我建议你先做这三件事特别是第一次在ARM设备上装软件的朋友。第一步确认系统架构。用uname -m查看内核架构如果输出aarch64说明是64位ARM系统输出armv7l或者armv6l说明是32位系统。再用dpkg --print-architecture确认软件包架构aarch64的机器对应arm64armv7l的机器对应armhf。这两个命令的输出要匹配否则你后面加软件源、装二进制包很可能会报“架构不支持”的错误。第二步确认Ubuntu版本和CPU核数。cat /etc/os-release看版本号20.04、22.04、24.04的软件源策略不一样。nproc命令看CPU核数这决定了你编译Redis的时候要不要加-j参数以及加几。我在一块4核的RK3399开发板上用make -j4编译Redis大概两分多钟如果无脑加-j8反而会因为内存不足把编译进程挤爆。第三步更新软件源并安装基础编译工具。sudo apt update先把源刷一遍然后sudo apt install -y build-essential tcl安装GCC、make这些基础工具。tcl是Redis源码自带测试套件需要的如果你打算跑make test这个包不能省。之所以先装编译工具是因为即使你准备用apt直接装Redis万一官方源里的版本不符合需求转源码编译的时候也不用回头再装依赖。2. 方案选型apt安装还是源码编译别拍脑袋决定安装Redis的方式不止一种但我们在ARM环境里真正可行的主流方案其实就两个用Ubuntu官方源里的apt包或者下载Redis官方源码自己编译。这两个方案各有利弊而且这个利弊在ARM平台上会比x86上更明显。2.1 两种安装方式的优缺点对比我把两种方式的对比直接放在表格里方便你对照选型对比维度apt安装redis-server源码编译安装安装速度几分钟内完成看设备性能通常5-20分钟版本新鲜度跟随Ubuntu源往往滞后官方最新版可自行选择依赖管理自动处理省心需手动安装编译依赖定制性低只能装源里的默认版本高可指定编译参数和安装路径服务化支持自动生成systemd服务需手动写service文件ARM兼容性官方已经适配基本无坑可能遇到jemalloc等编译问题卸载升级apt统一管理方便手动管理稍麻烦从表里能看出来apt方案最大的优势是省心和稳定Ubuntu官方源里的Redis包是经过测试适配的直接装完就有systemd服务开机自启都配好了。源码编译方案的优势是版本新、可定制比如你想用Redis 7.2的新特性但Ubuntu 20.04源里只有5.0那只能自己编译。2.2 什么场景选哪种方案我的判断标准我在不同设备上两种方案都试过总结出来的经验判断标准是这样如果只是要在ARM设备上跑一个常规的Redis实例给应用做缓存、存Session那apt是绝对的首选。原因很简单维护成本低apt升级或者卸载都省事而且Ubuntu源里的Redis配置默认做了合理的安全设置开箱即用。如果你需要最新版Redis的特性比如Redis 7.x的Function、Sharded Pub/Sub或者你是一个依赖Redis的组件开发者需要精确控制编译参数和版本那源码编译更合适。还有一个常见的场景是离线安装内网环境没法apt update手头也没有deb包那就只能找一个同架构的机器编译好或者直接拿源码到目标机器上编。另外提一下交叉编译这个事。有人问能不能在x86机器上交叉编译ARM版Redis然后拷到开发板上直接用。理论上可以openstav、arm-linux-gnueabihf这些工具链都能干这个活但实际操作中我很不推荐除非你目标设备的性能实在太弱、编译一次要半小时以上。原因是Redis这类自包含的软件本机编译本来就很快而交叉编译需要处理include路径、链接库、运行时依赖等一系列问题稍不注意编译出来的二进制在目标设备上跑不起来排查成本远超省下来的那点编译时间。3. 实操落地ARM Ubuntu上装Redis完整流程选定方案之后就可以动手了。这一节我把两种安装方式的完整过程都写出来每一步都解释清楚为什么要这么做以及可能遇到的问题。3.1 方式一apt安装适合绝大多数场景apt方式安装Redis在ARM Ubuntu上非常顺畅前提是你装的是arm64系统。在树莓派4这类设备上步骤跟x86基本没区别这是因为Ubuntu源里已经准备好了arm64架构的redis-server二进制包。具体步骤很简单sudo apt update sudo apt install -y redis-server安装完成后系统会自动创建一个redis用户生成systemd服务文件并把服务设置为开机自启。验证安装是否成功用下面这两条命令systemctl status redis-server redis-cli ping如果一切正常systemctl状态显示active (running)redis-cli ping返回PONG。这个PONG就是Redis服务器在告诉你“我活着而且网络通路正常。”安装完以后建议看一下配置文件位置和Redis版本redis-server --version sudo cat /etc/redis/redis.confUbuntu源里的默认配置做了几件事只绑定127.0.0.1开启protected-modedaemonize设置为yes由systemd托管服务所以配置里的daemonize其实会被覆盖。这些默认值对单机缓存场景是安全的不用改也能直接用。3.2 方式二源码编译需要新版本时的首选源码编译的流程要稍微长一些但每一步都不复杂。核心步骤是下载源码、解压、编译、安装。先到Redis官网确认最新稳定版版本号然后下载对应源码包。以7.2.4为例cd /opt sudo wget https://download.redis.io/releases/redis-7.2.4.tar.gz sudo tar -xzf redis-7.2.4.tar.gz cd redis-7.2.4编译前先检查一下GCC版本Redis 7.x要求GCC 4.8以上ARM Ubuntu 20.04默认的GCC 9完全够用gcc --version然后执行编译。这一步在ARM设备上特别要注意内存限制小内存设备不要用高并行度make -j2如果编译过程中报jemalloc相关的错误比如找不到头文件或者链接失败切换成libc分配器重新编译即可make distclean make MALLOClibc -j2编译完成后建议先跑一下自带测试套件需要安装tclsudo apt install -y tcl make test这里有个值得说明的点make test在ARM设备上跑的时间会比较长我的经验是性能和树莓派3B差不多的设备跑完整个测试套件大约需要20-40分钟。如果设备性能太差或者时间紧张可以选择跳过这一步但生产环境建议还是跑一遍它能暴露很多运行期才会出现的问题。测试通过后执行安装。我不建议直接make install装到默认的/usr/local/bin而是指定一个PREFIX方便后续管理和卸载sudo make install PREFIX/usr/local/redis这样Redis的可执行文件会安装到/usr/local/redis/bin目录下。可以把bin目录加进PATHecho export PATH$PATH:/usr/local/redis/bin ~/.bashrc source ~/.bashrc验证安装同样用版本命令/usr/local/redis/bin/redis-server --version3.3 redis.conf关键配置项拿过来就能改不管用哪种方式装最终都要落到配置文件上。Redis默认的redis.conf在apt安装时位于/etc/redis/redis.conf源码编译时位于解压目录下的redis.conf。配置项很丰富但对于ARM设备上的常规部署这几个参数是你必须搞清楚的。daemonize参数决定Redis是否以守护进程方式运行。apt安装时因为systemd接管了服务这个参数实际意义不大。但如果你是用源码编译后手动启动建议把daemonize设为yes否则你在终端启动Redis关闭终端Redis也跟着退出。bind和protected-mode是访问控制相关的。默认bind 127.0.0.1只能本机访问如果想让局域网内的其他机器连接Redis需要改成bind 0.0.0.0并把protected-mode设为no。注意这样修改后相当于对外暴露了Redis必须设置requirepass密码否则任何人都能读写你的数据。我见过不少人在开发板上改了bind忘了设密码结果Redis变成矿池肉鸡的案例。maxmemory和maxmemory-policy决定了Redis内存上限和数据淘汰策略。ARM设备内存普遍不大这两个参数尤其关键。比如设备有4G内存分配给Redis的maxmemory可以设为2gb淘汰策略用allkeys-lru这样当数据量超过2G时Redis会按LRU算法淘汰不常用的key。requirepass设置访问密码格式就是一行明文密码。如果Redis暴露在非本机网络这一步绝对不能省别存侥幸心理。appendonly决定是否开启AOF持久化。如果Redis只做缓存、数据丢了可以重建建议直接把appendonly改成no减少磁盘IO开销。如果是生产环境要持久化那么appendonly yes并配置appendfsync everysec在性能和可靠性之间取个平衡。4. 踩坑实录编译报错、启动失败与服务化问题这一节是我最想分享的内容。ARM环境下装Redis真正耗时间的往往不是安装本身而是排错。我把踩过的坑和解决方案整理出来你遇到类似问题直接对号入座就可以了。4.1 ARM上编译的典型报错以及对应解法第一个高频报错是编译过程中出现“jemalloc.h: No such file or directory”。这个问题的根源是Redis内置的jemalloc在特定ARM环境下构建失败导致后续编译找不到头文件。解决办法就是我前面提到的用make MALLOClibc切换到系统malloc。要注意的是如果第一次编译失败过再编译前一定要先make distclean清理现场否则旧的对象文件会干扰新编译。第二个常见问题是“fatal error: stdatomic.h: No such file or directory”。这种情况多见于32位ARM系统因为Redis的某些原子操作依赖GCC的__atomic内置函数而老旧的工具链不完整。解决办法是升级GCC或者换用64位的ARM系统。如果实在要在32位环境下跑可以用make CFLAGS-marcharmv7-a指定架构优化参数但不保证百分百能过。第三个问题不是编译报错而是编译过程被OOM Killer杀死。ARM开发板内存小make -j参数开太高GCC同时编译多个文件会瞬间吃掉大量内存。我见过一台1G内存的树莓派3B用make -j4编译时直接卡死dmesg里看到一堆Out of memory日志。解决办法很简单把并行度降下来甚至直接用make -j1单线程编译虽然慢一点但稳。4.2 启动失败和运行异常的排查思路编译安装完Redis运行redis-server /path/to/redis.conf后可能遇到启动失败的情况。这时候先别急着看日志配置文件我建议用前台模式跑一下直接看输出的报错信息/usr/local/redis/bin/redis-server /opt/redis-7.2.4/redis.conf --daemonize noRedis在前台模式下会把启动日志直接打到终端任何报错信息都一目了然。最常见的前台启动报错是“Cant open the log file”这个是因为配置里指定的日志目录不存在或者权限不足。解决办法是提前建好目录并授权或者暂时把logfile改成空字符串输出到stdout。另一个很典型的坑是“Address already in use”。这种情况通常是上一次运行Redis的进程没被杀干净。排查方式ps -ef | grep redis sudo lsof -i :6379把残留进程kill掉再启动。注意kill Redis千万别用kill -9Redis的持久化机制依赖优雅退出时的SAVE操作强杀可能导致数据丢失。应该用redis-cli shutdown或者kill加普通信号让Redis自己处理退出流程。如果你改了bind 0.0.0.0外部设备连不上Redis先ping一下这台设备的IP确认网络通不通。网络通的话再确认防火墙有ufw的话执行sudo ufw allow 6379开放端口。ARM开发板上很多精简系统默认没有防火墙规则这点跟服务器不太一样。4.3 把Redis注册成systemd服务apt方式安装的Redis会自动生成systemd服务但源码编译安装的Redis就需要自己动手写service文件了。这一步不复杂但有几个小地方容易被忽略。在/etc/systemd/system/redis.service创建服务文件[Unit] DescriptionRedis Server Afternetwork.target [Service] Typeforking ExecStart/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf ExecStop/usr/local/redis/bin/redis-cli shutdown Restartalways Userredis Groupredis RuntimeDirectoryredis RuntimeDirectoryMode0755 PIDFile/var/run/redis/redis-server.pid [Install] WantedBymulti-user.target这里有几个关键点。Typeforking是因为redis.conf里daemonize yesRedis启动后会fork出子进程systemd需要根据PIDFile确认服务是否启动成功。如果redis.conf里daemonize no那Type要改成simple这样systemd直接用主进程托管。Userredis和Groupredis是专门为Redis创建的运行用户避免Redis以root权限运行。创建用户可以用useradd --system --user-group redis。注意Redis的数据目录比如默认的/var/lib/redis和日志文件要chown给redis用户否则Redis写不了数据。写完service文件后执行sudo systemctl daemon-reload sudo systemctl enable redis sudo systemctl start redis这里有个经验小技巧如果你在service文件里把Type配置错了启动后systemctl status会显示failed但直接跑redis-server可能一切正常。遇到这种情况先去检查Type和daemonize的匹配关系这是最容易被忽视的点。5. ARM小内存设备上的性能优化与调参装好、跑起来只是第一步想让Redis在ARM设备上有稳定表现还需要针对硬件特点做一些调优。不同ARM设备差异巨大同一套配置在服务器上没问题挪到开发板上可能就会出问题。5.1 内核参数调整让Redis运行更稳健ARM设备上Redis最常见的运行问题是持久化时的阻塞。RDB持久化要用fork创建子进程而fork需要复制父进程的页表。物理内存越大、Redis占用的内存越多fork耗时越长期间整个Redis进程会阻塞。这时候系统会提示WARNING overcommit_memory is set to 0! Background save may fail under low memory condition.解决方法是把overcommit_memory设置为1。这个参数在内核里控制内存分配策略0表示启发式拒绝明显超支的内存请求1表示总是允许超支。Redis在RDB持久化时fork子进程子进程会预留一份内存如果不允许overcommitfork容易失败。设置方式sudo sysctl vm.overcommit_memory1要让配置永久生效写入/etc/sysctl.confecho vm.overcommit_memory1 | sudo tee -a /etc/sysctl.conf sudo sysctl -p另一个建议关闭的内核特性是透明大页THP。Redis官方文档明确建议关闭因为THP会导致Redis在fork时出现更大的内存延迟峰值。关闭方式echo never | sudo tee /sys/kernel/mm/transparent_hugepage/enabled同样要持久化得写到/etc/rc.local或者单独的systemd单元里因为/sys路径下的设置重启后会重置。还有一个ARM设备上容易被忽略的方面CPU频率调整策略。很多开发板的CPU默认用conservative或powersave调频策略Redis这种突发负载会被影响响应时间。把调频策略改成performance模式能显著减少延迟波动echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor树莓派上新版内核默认用ondemand策略性能基本可以接受但如果对延迟敏感建议切到performance测试一下。这个在Linux发行版上不是所有的ARM设备都支持部分设备没有调频接口命令执行报错说明当前内核不支持直接忽略就行。5.2 Redis配置层面的细节调整内核层调完Redis配置层还有几个值得注意的参数。maxmemory的设置原则我的建议是分配给Redis的内存不超过物理内存的60%到70%。比如一台4G内存的RK3399开发板maxmemory设置为2.5gb比较安全留出余量给系统和其他应用。如果设置太高Redis占满内存后系统OOM Killer可能连Redis带其他重要进程一起干掉。Lazy Free相关的参数建议默认保持开启。Redis 4.0以后引入了lazy free机制可以异步释放大key的内存避免主线程被阻塞。默认配置lazyfree-lazy-eviction yes配合maxmemory使用效果很好当Redis触发内存淘汰时大key的删除异步执行。还有网络相关的参数tcp-backlog。默认值是511但如果你的ARM设备内核socket队列配置较小在高并发连接场景下可能出现连接失败。解决办法是在系统层面调大somaxconnecho 1024 | sudo tee /proc/sys/net/core/somaxconn如果Redis不需要持久化建议把save相关配置注释掉并设置appendonly no。这样一来Redis的全部数据都在内存里省去了磁盘IO开销和fork阻塞的风险。开发板上跑缓存类应用这个配置策略非常实用。5.3 一个最简单也最容易被忽视的验收方法配置调优完很多人直接就开始用了根本不知道这台设备上的Redis性能到底处于什么水平。我建议用Redis自带的基准工具测一下基线了解你的设备能力上限redis-benchmark -q -n 100000 -c 50这条命令模拟50个并发连接、10万次请求测试Redis的吞吐量。我在不同的ARM设备上测过数据差异非常大一颗主流的4核A72架构处理器SET/GET大约每秒5-8万次而树莓派Zero这类单核超低功耗设备大约只有1-2万次。知道数据差距之后你在做容量规划时心里就有底了不会用x86服务器的标准硬套ARM设备。如果benchmark结果比同型号设备的平均值差一大截优先检查是不是CPU调频策略有问题其次是内存频率和swap状态。有时候开发板的swap配置在SSD上频繁换页会严重拖垮性能可以临时关闭swap试试sudo swapoff -a实测后发现很多性能问题根本不是Redis配置的原因而是底层系统资源安排不合理。所以遇到性能不达标别急着怀疑Redis先把系统基线摸清楚。我在多台ARM设备上跑Redis最大的体会就是这个组合上限比想象中高、下限也比想象中低。配置得当、系统调优到位Redis完全可以在ARM设备上扛住不错的并发量但要是忽略了架构特性和内存限制一个看似正常的配置就能让设备反复重启。最后再分享一个小技巧如果你在多台同型号ARM设备上都要装Redis只需要在一台上用源码编译好然后直接把整个/usr/local/redis目录拷贝到其他机器就能用前提是系统glibc版本接近。这样可以省去每台设备重复编译的等待时间。