ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Linux下启动Redis的完整实践:从裸命令到systemd与容器

Linux下启动Redis的完整实践:从裸命令到systemd与容器 “在 Linux 下启动 Redis”这个标题看着很简单但真上手你会发现水挺深。我见过不少朋友第一次在服务器上装完 Redis直接敲redis-server跑起来是跑起来了窗口一关服务就没了还有人在云服务器上启动成功结果用自己的电脑连被 Redis 的 protected mode 挡住报一大堆英文错误完全摸不着头脑。这篇文章我就把自己平时在 Linux 环境里启动 Redis、排查问题的那套经验写出来覆盖从“下载安装完”到“服务稳定跑起来”的全过程也会顺便讲清楚前台启动、后台启动、systemd 托管和容器启动的区别。写之前先说明这是一篇动手经验帖不是官方文档翻译所以我会尽量用实际命令和踩过的坑来说事。不管你是刚转行做运维、写后端想本地调试还是要在生产服务器上把 Redis 拉起来这篇都能给你一套直接能跟着走的思路。内容重点放在“为什么这么做”而不是“照着抄就行”因为 Redis 报错信息有时候挺会骗人的不懂背后的原理换个环境又得抓瞎。1. 先把“启动”这两个字拆开想清楚1.1 你是想临时跑一下还是让它长期服役很多人对“启动 Redis”的理解就是执行redis-server看到终端里出现 Redis 的 logo 和版本号就认为完事。但不同场景下的启动要求完全不同。如果你只是在本地开发环境里验证某个功能想跑一个临时 Redis 实例那确实越简单越好甚至不需要配置文件直接redis-server --port 6380就能起一个不走默认端口的实例。但如果你是给公司的测试环境或者生产环境启动 Redis那就不能这么随便了。你得考虑它是不是开机自启、日志写到哪里、PID 文件有没有生成、如果进程死了怎么拉起、内存分配策略是不是提前调好了。这些东西都不在redis-server表面功夫里但直接影响你能不能“安稳地用下去”。所以第一个建议是先明确你的使用场景再决定启动方式。1.2 确认环境与版本信息动手启动之前先把 Redis 版本和系统环境确认清楚这能省掉后面一半的麻烦。redis-server --version redis-cli --version如果命令提示找不到那你还没安装或者没把安装路径加进 PATH。我见过很多次“启动失败”最终原因不是 Redis 本身有问题而是根本没装上只是在某个目录里解压了源码包。下载和编译安装也是一条常见路径。从源码编译的话需要机器上有 gcc 和 make 工具链。编译过程其实很稳定但要注意 Redis 6 之后对编译器版本有些要求如果系统太老编译时就会报错。wget https://download.redis.io/releases/redis-7.0.12.tar.gz tar xzf redis-7.0.12.tar.gz cd redis-7.0.12 make编译完以后src/redis-server就是可执行文件。我习惯接着执行make install这样程序会被放到/usr/local/bin下后续在任何目录里都能直接敲redis-server不用老记着源码路径。还需要确认系统内存情况。Redis 是内存数据库看起来简单但如果你给它设置maxmemory 0不限制它会在写入量大的时候吃光系统内存然后被 Linux 的 OOM Killer 直接干掉。启动前用free -h看一眼内存心里有数。1.3 选启动方式前台、后台、系统服务还是容器到了真正启动这一步你会发现启动 Redis 有不止一种方式。我总结下来主要就四种第一前台启动。终端直接执行redis-server所有日志打印在当前窗口。好处是你能立即看到详细输出适合首次启动验证配置。坏处是 CtrlC 一按服务就停终端关闭服务也没了。第二后台启动。通过修改配置文件里的daemonize yesRedis 启动后自动 fork 到后台运行终端可以继续干别的。第三systemd 管理。把 Redis 做成一个 systemd service设置开机自启、崩溃自动重启这是生产环境最常见的管理方式。第四容器方式。用 Docker 起一个 Redis 容器比如docker run -d --name redis -p 6379:6379 redis:7。容器方式的好处是隔离干净、扩容方便但要注意容器里的数据持久化问题不能只管启动不管数据。这几种方式不是互斥的。我经常在本地调试时用前台启动方便看日志在测试环境用 systemd在公司的微服务体系里用 Docker。理解它们各自的特点你才知道选哪种。2. 配置文件不是摆设启动参数藏在里面2.1 配置文件位置与加载顺序很多第一次接触的人会有疑问我执行redis-server时为什么不是按照某个配置文件启动这是因为 Redis 支持无配置启动默认用内置参数相当于一个最小的可用状态。它会在默认路径找配置文件吗会尝试但不强制。如果redis.conf存在于当前目录或/etc/redis下你不指定它也不会主动加载。所以规范的启动方式应该是redis-server /etc/redis/redis.conf我这里习惯于把配置文件拷到/etc/redis/下并用实例名区分不同端口mkdir -p /etc/redis cp redis.conf /etc/redis/redis-6379.conf配置文件里其实都是参数 值的形式首行空行和注释都用#。你不需要背太多优先看下面几个和启动强相关的。2.2 和启动强相关的几个参数我在配置 Redis 的时候会重点看这几个参数bind决定 Redis 监听在哪些 IP 上。默认是127.0.0.1 -::1也就是只允许本机连接。如果想让局域网或云服务器外部访问就要改成0.0.0.0或具体网卡 IP。但改成0.0.0.0之后必须配合密码和保护模式使用否则等于把服务裸奔到公网。port默认 6379。如果机器上跑多实例可以改成 6380、6381 等。protected-mode默认 yes。这是 Redis 自己加的保险意思是当它没有设置密码、又监听了非本机地址时会拒绝来自外部的访问。很多人启动后外部连不上报错“DENIED Redis is running in protected mode”就是这个参数在起作用。daemonize控制是否后台运行。默认是 no。如果你用或nohup方式手动丢后台也可以不用改它但规范做法是让 Redis 自己 daemonize。pidfile后台运行后把进程号写到一个文件里比如/var/run/redis_6379.pid。这方便 systemd、监控脚本、排查进程时使用。logfile日志路径。如果不设置日志会打到标准输出。如果设置daemonize yes时又不配 logfile日志会直接消失你出了什么问题都看不到这是新人最容易被坑的点。maxmemoryRedis 最多能用多少内存。建议设置成物理内存的一半甚至更小比如maxmemory 2gb。否则一旦写入量上去Redis 会无限制占用内存操作系统 OOM Killer 会直接杀掉进程。requirepass设置访问密码。生产环境必须设置本地临时跑可以不设。2.3 一个常见误区数据持久化配置和启动没关系有人觉得 RDB 和 AOF 是“存数据”用的跟启动没关系。实际上它们直接影响启动成功与否。我遇到过一个真实案例有人把appendonly yes打开AOF 文件因为之前写入异常损坏了结果重启 Redis 的时候进程起不来日志里到处是“Bad file format reading appendonly file”。所以如果你配置了 AOF记得检查appendonly.aof文件是否存在且完整。RDB 配置里有两个参数容易忽略save 900 1 save 300 10这些表示多少秒内有多少次写操作就触发一次快照。如果你在压力很大的场景里频繁 fork 可能会影响性能。但这不是本文重点只提醒一句启动 Redis 时如果发现 fork 失败可能和系统的内存分配策略有关具体排查放在后面第五部分说。3. 实操启动从最简单的命令到系统级管理3.1 什么都不改先跑一次最小实例第一次接触 Redis我建议你先跑一个最小前台实例体会一下“启动成功”是什么样。redis-server --port 6379屏幕上会打印 Redis 版本号、运行模式、监听端口、PID 等信息。到这个状态说明 Redis 已经能跑了。此时你开另一个终端执行redis-cli -p 6379 ping正常情况下返回PONG。这就是最简单的启动验证。但注意我没有指定daemonize yes所以这个进程在前台占着终端。想退出直接 CtrlC。这种方式很适合第一次调试比如你怀疑某个参数写错了可以先带参数跑一次看它到底能不能正常起来而不需要先改配置文件再重启。3.2 让 Redis 在后台运行daemonize 与 nohup 的区别如果想让进程留在后台同时不能丢失日志信息我推荐的做法是在配置文件里把 daemonize 打开并指定 logfile。daemonize yes pidfile /var/run/redis_6379.pid logfile /var/log/redis/redis-6379.log dir /var/lib/redis然后启动redis-server /etc/redis/redis-6379.conf命令执行后终端不会一直挂着Redis 会自己 fork 到后台日志写入 logfile。你可以执行ps -ef | grep redis或redis-cli ping确认存活。有人图省事直接这样启动redis-server /etc/redis/redis.conf 这里用 shell 的把进程放到后台。这个方案的问题在于如果终端退出进程可能会收到 SIGHUP 挂断信号从而退出。虽然 Redis 有可能重新 fork但行为不稳定。如果要这样通常得加上nohupnohup redis-server /etc/redis/redis.conf /tmp/redis.log 21 但说实话既然配置里都有现成的daemonize yes我更建议直接用它而不是依赖 shell 层面的后台技巧。配置里有个细节值得注意如果daemonize yes启动时 Redis 会 fork 一次PID 会变化所以脚本里如果用$!去拿进程号拿到的可能不是最终 Redis 主进程。正确做法是看 pidfile。3.3 用 systemd 把 Redis 纳入统一管理生产环境里我遇到过最理想的方式还是 systemd。我一般在/etc/systemd/system/redis.service写这样一个单元文件[Unit] DescriptionRedis Persistent Key-Value Database Afternetwork.target [Service] Typeforking ExecStart/usr/local/bin/redis-server /etc/redis/redis-6379.conf ExecReload/bin/kill -s HUP $MAINPID ExecStop/bin/kill -s TERM $MAINPID Restartalways PIDFile/var/run/redis_6379.pid [Install] WantedBymulti-user.target这里有几个关键点Typeforking很关键。因为 Redis 配置里是daemonize yessystemd 需要知道主进程会 fork并且要通过 pidfile 确认实际服务的 PID。Restartalways表示 Redis 进程意外退出后自动拉起。但这不代表你要把“一直在自动重启”当成万能频繁崩溃说明背后有 bug该排查还是得排查。写完单元文件后执行systemctl daemon-reload systemctl start redis systemctl enable redis systemctl status redisenable是把服务加入开机自启不加这一句服务器重启后就只能手动拉起来。这句话很多人都知道要敲但真到了上线时总会有人漏掉。3.4 在 Docker 容器里启动 Redis思路不太一样容器里的 Redis 不是一个简单进程而是一个容器生命周期。如果你只是docker run一个 Redis命令通常是docker run -d --name redis-test -p 6379:6379 redis:7默认情况下容器的配置文件被封装在镜像内部。Docker 环境更推荐把数据目录和配置都挂载到宿主机方便升级和备份docker run -d \ --name redis \ -p 6379:6379 \ -v /data/redis:/data \ -v /etc/redis/redis.conf:/usr/local/etc/redis/redis.conf \ redis:7 redis-server /usr/local/etc/redis/redis.conf这里注意一个问题如果你用daemonize yes容器里 Redis 会 fork 到后台但容器的主进程是redis-server如果它 fork 之后父进程退出了容器会认为主进程结束然后 Docker 会停掉整个容器。所以在 Docker 里一定不要开 daemonize默认 no 反而是对的。这也是容器启动方式和传统启动方式差异最大的地方我见过有人直接把本机那套 daemonize 配置扔进容器容器起来就退查了很久才明白是 fork 的锅。4. 启动之后别急着庆祝4.1 redis-cli ping 和更多验证手段启动成功不等于“环境能用”我建议至少做三层验证。第一层进程级别。用命令确认进程确实存在ps -ef | grep redis-server如果看到类似redis-server *:6379这样的记录说明进程在跑。注意看是不是带上了完整配置路径有时候你会看到两个 redis-server一个是守护进程一个是正在执行 fork 的父进程需要稍等一下再观察。第二层CLI 级别。用redis-cli执行几个命令redis-cli -p 6379 ping redis-cli -p 6379 info serverinfo server里能看到 redis_version、运行时间、启动时间等。我一般会看uptime_in_seconds如果很小说明进程刚启动不久可能发生了重启。第三层数据写读级别。如果这是你第一次在某个环境里部署 Redis可以执行redis-cli set hello world redis-cli get hello这一步的意义不只是测试写入而是验证maxmemory和持久化配置有没有导致异常。如果出现OOM command not allowed when used memory maxmemory说明内存限制得太小了。4.2 看日志是启动排查的基本功启动之后日志一定要看。我习惯先确认日志文件位置tail -f /var/log/redis/redis-6379.log如果没配置 logfile日志会在终端直接打印。若你想新增日志参数又不想改文件可以启动命令里直接加redis-server /etc/redis/redis-6379.conf --logfile /var/log/redis/redis-6379.log启动日志里最核心的是这一行不同版本表述稍有差异Ready to accept connections看到这行基本说明启动流程走完了后面是网络监听阶段。如果日志里出现Cant open the log file: Permission denied说明运行用户没有目录写权限用ls -ld /var/log/redis看一下属主或者干脆调整目录权限。还有一种情况是日志里看不到任何输出进程也正常。那是因为配置了daemonize yes但没指定 logfile日志被丢弃了。不要慌张补上 logfile 再重启一次。4.3 远程连接前的可视化工具选型很多用 Windows 或者 Mac 做本地开发的人会想用一个图形化客户端看数据。常见的开源工具是 Another Redis Desktop Manager还有 Redis Desktop Manager 的老版本。连接 Linux 服务器上的 Redis 时一定会经历这些配置host 填服务器 IPport 填 6379password 填 requirepass 里的密码如果 Redis 只 bind 127.0.0.1客户端连不上需要先处理 bind。这里我不推荐直接把bind 0.0.0.0protected-mode no整套关掉风险太大。更好的做法是用 SSH 隧道ssh -L 6379:127.0.0.1:6379 useryour_server_ip然后在本地客户端里填127.0.0.1:6379连接。这样安全性和方便性都兼顾也是我比较推荐的方式。5. 启动阶段高频故障与排查思路5.1 端口被占用Redis 起不来日志里最典型的报错是这样的Could not create server TCP listening socket *:6379: bind: Address already in use这说明 6379 已经被别的进程占用了。先查ss -lntp | grep 6379看到 PID 后确认是不是原来那个 Redis 没被干净退出。如果不是 Redis 在用说明端口冲突。解决办法各有不同如果确实是旧 Redis 进程残留kill掉再启动。如果端口被其它程序占用换一个 Redis 端口比如 6380修改配置文件的port。这里提醒一句不要习惯性用kill -9杀 Redis。Redis 有持久化任务时强杀容易导致 AOF 或 RDB 写入不完整重启后可能加载失败。优先用redis-cli shutdown nosave或redis-cli shutdown save优雅停机。5.2 内存分配策略导致的 fork 失败如果你的 Redis 日志里有类似这样的信息# Background saving terminated by signal 11 Cant save in background: fork: Cannot allocate memory不要只盯着“内存不够”这四个字很可能是vm.overcommit_memory策略问题。Linux 默认在申请内存时可能过度承诺也可能根据情况拒绝。Redis 做 RDB 持久化时 fork 子进程需要映射和父进程同样的内存空间如果 overcommit 设置为 2kernel 就会严格限制。解决办法是临时调整echo vm.overcommit_memory 1 /etc/sysctl.conf sysctl vm.overcommit_memory1这个参数在生产环境最好提前配好别等到 Redis 触发 BGSAVE 才去查。5.3 protected mode 和防火墙联手挡路这是一个非常高频的问题。启动成功后你用redis-cli在服务器本机执行ping一切正常但远程客户端连不上。日志里又没有报错只有客户端那边报Connection refused或DENIED Redis is running in protected mode because protected mode is enabled and no password is set for the default user.如果云服务器上有安全组一定要先确认安全组放行了 6379 端口。有时候 Redis 本身配置没问题是云厂商安全组默认拦着。之后再确认本机防火墙firewalld环境下可以检查firewall-cmd --list-all如果没有放行 6379执行firewall-cmd --zonepublic --add-port6379/tcp --permanent firewall-cmd --reload如果既不打算设密码又想允许远程连接把protected-mode设成 no 不是不行但这相当于裸奔我强烈不推荐。生产环境一定要设requirepass然后用带密码的方式连接。5.4 文件描述符限制这个坑通常发生在高并发场景。Redis 作为网络服务每个客户端连接都会占用一个文件描述符。如果系统对进程的限制太低启动时可能还行运行到一定连接数就会出问题。Linux 里临时调整ulimit -n 65535但系统重启后又会恢复所以更稳妥的是在 systemd 单元文件里加LimitNOFILE65535顺便提一下Redis 配置文件里也有一个maxclients默认 10000。如果系统 ulimit 不够这个值再高也白搭。排查时别只看 Redis 配置。5.5 启动成功但立刻退出怎么定位这个问题比“完全起不来”更隐蔽。有时候你执行redis-server屏幕一闪而过进程没了。大部分情况是启动时某个配置不合法。解决办法已经不是盲目重试而是让日志先落下来redis-server /etc/redis/redis-6379.conf --logfile /tmp/redis-debug.log然后看日志。常见的爆点有几类我分别说下Unknown directive配置文件里写错了参数名Redis 直接退出。这通常发生在网上复制配置时版本不匹配Redis 4 的配置拿到 Redis 7 里跑。Cant chdir to ./dir目录不存在。Redis 配置了持久化目录但这个目录没有创建或者运行用户没有写权限。Could not create server TCP listening socket网络或特权问题。如果 bind 了一个非本机 IP但该 IP 没在系统网卡上启动也可能失败。我自己的排查习惯是这样的先看日志再上ss看端口再用redis-cli做连通性测试最后才去怀疑配置问题。启动 Redis 这件事越按顺序排查越省时间。6. 收个尾关于 Redis 启动我的真实体会我个人在实际操作中的经验是Redis 启动本身并不难真正难的是启动之外的管理意识。很多人只把 Redis 当成一个缓存服务随手一个命令拉起来后续内存、日志、持久化、权限设置全都不管等到出了问题才开始翻文档。如果你用的是 Linux 服务器尤其云上的服务器请牢牢记住“启动”不只是一瞬间的状态它意味着一个长期运行的服务正式进入了你的责任范围。另一点是我常在团队里强调的别在生产环境用裸命令启动 Redis。裸命令很快但它没有日志落盘、没有 PID 文件、没有开机自启、没有资源限制一旦你离开这个终端或者服务器重启所有依赖 Redis 的服务都会立刻被打回原形。最后分享一个小技巧如果你需要经常处理多实例 Redis建议把配置文件目录做成/etc/redis/实例文件按端口命名比如redis-6379.conf、redis-6380.conf。启动命令统一用redis-server /etc/redis/redis-6379.conf配合 systemd 和日志监控后续无论是扩容还是排查都会顺手很多。希望这篇内容能帮你在 Linux 上少踩几个坑把 Redis 稳稳跑起来。
返回列表