跳到主要内容

Redis 安装与快速上手

装哪种、装哪版​

示例环境是 Ubuntu 22.04,目标是跑起一个能连、能读写的 Redis 7.x。Ubuntu 22.04 官方源里的 redis-server 停在 6.0.16,功能上够学习用,但 7.x 的 ACL 完善度、AOF 多部分、Function 等特性都没有。三条路按需选:

方式拿到的版本适合场景维护成本
apt 安装系统源 6.0.16,或官方源 7.x快速验证、标准运维低,systemd 托管
源码编译想装哪个版本装哪个需要特定版本、要调编译参数中,服务单元自己写
Docker镜像 tag 决定本地开发、临时环境、容器化部署低,但要管好配置和卷

不管哪种方式,装完先验证客户端:

redis-cli -v

输出类似 redis-cli 7.2.5。注意这只说明客户端装好了,服务端有没有起来、连不连得通是另一回事。

方式一:apt 安装​

最省事的一条路,适合先把环境跑起来:

sudo apt update
sudo apt install -y redis-server
redis-server --version
redis-cli -v
systemctl status redis-server --no-pager

apt 装的包目录约定很规整,后面改配置、找日志都按这个来:

  • 配置文件:/etc/redis/redis.conf
  • 数据目录:/var/lib/redis
  • 日志:默认写 syslog,也可以在配置里改成文件
  • 服务名:redis-server,装完默认开机自启
  • 运行用户:redis

想要 7.x 又不想编译,用 Redis 官方 apt 源。注意官方源的包名是 redis,和系统的 redis-server 会冲突,先卸掉旧的:

sudo apt remove -y redis-server
sudo apt install -y lsb-release curl gpg

curl -fsSL https://packages.redis.io/gpg | \
sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
sudo chmod 644 /usr/share/keyrings/redis-archive-keyring.gpg

echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | \
sudo tee /etc/apt/sources.list.d/redis.list

sudo apt update
sudo apt install -y redis

装完 /etc/redis/redis.conf 的结构和官方源码包基本一致,服务名同样是 redis-server。

方式二:源码编译​

需要精确控制版本、或者想自己指定安装路径时用这条路。先补编译依赖:

sudo apt install -y build-essential tcl pkg-config

然后下载、编译、安装。版本号换成你要的即可,7.2.x 是当前稳定的 7.x 分支:

cd /usr/local/src
sudo curl -LO https://download.redis.io/releases/redis-7.2.5.tar.gz
sudo tar -xzf redis-7.2.5.tar.gz
cd redis-7.2.5
sudo make -j"$(nproc)"
sudo make install

make install 会把 redis-server、redis-cli、redis-sentinel、redis-benchmark 拷到 /usr/local/bin。如果不想污染系统路径,用 sudo make install PREFIX=/opt/redis,之后二进制在 /opt/redis/bin 下。

接着准备目录、用户和配置:

sudo mkdir -p /etc/redis /var/lib/redis /var/log/redis
sudo cp redis.conf /etc/redis/redis.conf
sudo useradd -r -s /sbin/nologin redis
sudo chown -R redis:redis /var/lib/redis /var/log/redis

源码安装没有 systemd 单元,得自己写一个 /etc/systemd/system/redis.service:

[Unit]
Description=Redis persistent key-value database
After=network.target

[Service]
Type=simple
User=redis
Group=redis
ExecStart=/usr/local/bin/redis-server /etc/redis/redis.conf
Restart=always

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now redis
sudo systemctl status redis --no-pager
编译的两个坑

一是内存不够:make 阶段如果被 OOM Killer 干掉,用 make -j2 降并发,或者临时加 swap。二是 make test 需要 tcl,不装会跳过测试直接报错;生产环境建议至少在一台测试机上跑一遍 make test 再上线。

方式三:Docker​

本地验证最干净的方式。官方镜像的入口就是 redis-server,把配置文件和参数接在后面即可:

mkdir -p ~/redis/conf ~/redis/data
# 把下面的最小配置存成 ~/redis/conf/redis.conf

docker run -d --name redis \
-p 6379:6379 \
-v ~/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

docker exec -it redis redis-cli ping

参数含义:-p 把端口映射到宿主机;第一个 -v 挂配置文件;第二个 -v 把数据目录挂出来,容器删了数据还在;最后的 redis-server ... 覆盖镜像默认启动命令,让它读我们的配置。

容器默认没有密码

官方镜像不挂配置直接跑时是无密码的,只要 -p 6379:6379 发布到公网,基本等于把数据库送人。本地开发也建议只映射到 127.0.0.1:6379:6379,或者直接在配置里写 requirepass。

redis.conf 最小配置​

不管哪种安装方式,先让下面这几项是对的:

# 只监听本机和内网网卡,绝不写 0.0.0.0
bind 127.0.0.1 -::1
# 保护模式:没密码又没 bind 时拒绝外部连接
protected-mode yes
port 6379
# systemd / Docker 托管时必须 no,否则服务会「启动成功但进程退到后台」
daemonize no
# 强密码,至少 32 位随机串
requirepass Your_Strong_Password_Here
# 数据与日志路径,按实际目录改
dir /var/lib/redis
logfile /var/log/redis/redis-server.log
# 持久化:AOF 每秒刷盘
appendonly yes
appendfsync everysec
# 内存上限与淘汰策略
maxmemory 2gb
maxmemory-policy allkeys-lru

四项关键配置逐个说:

  • bind:监听地址白名单,可以写多个,例如 bind 127.0.0.1 10.0.0.11。写 0.0.0.0 表示所有网卡,除非前面有安全组和防火墙,否则别这么干。
  • protected-mode:3.2 引入的兜底保护。只有「没配 bind + 没设密码」时才生效,此时只接受本机回环连接。它不是访问控制,配了 bind 或密码后它就不管事了。
  • requirepass:设置后所有连接都要先 AUTH。6.0 之后更推荐 ACL,用 ACL SETUSER app on >password ~app:* +@read +@write 给不同应用分配不同账号和 key 权限,比一个全局密码精细得多。
  • daemonize:yes 会让进程 fork 到后台,systemd 会以为服务已经退出。用 systemd 就写 no,让 systemd 直接托管前台进程;用容器也写 no。

改完配置重启并确认加载的是新配置:

sudo systemctl restart redis-server
sudo systemctl status redis-server --no-pager
redis-cli CONFIG GET maxmemory maxmemory-policy appendonly

第一次连接​

不带参数时 redis-cli 默认连 127.0.0.1:6379:

redis-cli -h 127.0.0.1 -p 6379

设了密码就要带 -a,并加 --no-auth-warning 抑制「明文密码」警告:

redis-cli -h 127.0.0.1 -p 6379 -a 'Your_Strong_Password_Here' --no-auth-warning
-a 会把密码留在历史里

-a 的密码会进 shell history,也会出现在 ps 的命令行里,同机其他用户能看到。生产上更稳的写法是环境变量 export REDISCLI_AUTH='...',或者进交互式后用 AUTH 命令手动认证。--no-auth-warning 只是把警告藏起来,不解决泄露问题。

连上之后先来一轮最基础的读写:

127.0.0.1:6379> PING
PONG
127.0.0.1:6379> SET user:1001:name "张三"
OK
127.0.0.1:6379> GET user:1001:name
"张三"
127.0.0.1:6379> SET session:abc123 token-xyz EX 3600 NX
OK
127.0.0.1:6379> TTL session:abc123
(integer) 3600
127.0.0.1:6379> EXISTS user:1001:name
(integer) 1
127.0.0.1:6379> KEYS user:*
1) "user:1001:name"
127.0.0.1:6379> DEL user:1001:name
(integer) 1

几个命令的行为值得记住:

  • SET ... EX 3600 NX:带过期时间 + 不存在才设置,一条命令原子完成,缓存和锁都这么写。
  • TTL 返回 -1 表示 key 存在但没设过期,-2 表示 key 不存在。别把这两个值搞混。
  • KEYS 是 O(N) 全库扫描,只用于本地演示,线上执行会阻塞整个实例。要按模式找 key,用游标式的 SCAN:
127.0.0.1:6379> SCAN 0 MATCH user:* COUNT 100
1) "0"
2) 1) "user:1001:name"

SCAN 返回的游标为 0 表示遍历结束;生产代码要循环调用直到游标归零,并且接受「同一个 key 可能返回多次」。

非交互场景直接用命令行模式,写脚本、做巡检都方便:

# 单条命令
redis-cli -h 127.0.0.1 -p 6379 -a "$REDIS_PASS" --no-auth-warning SET demo:key hello

# 批量执行命令文件
redis-cli -h 127.0.0.1 -p 6379 < commands.txt

# 按模式扫描(内部封装的 SCAN)
redis-cli -h 127.0.0.1 -p 6379 --scan --pattern 'user:*'

# 实时看命令(排障用,QPS 高时慎用)
redis-cli -h 127.0.0.1 -p 6379 MONITOR

安全警告:默认不设密码就是给挖矿留门​

这一节不是危言耸听。Redis 未授权访问是互联网上被利用得最充分的问题之一,从 2017 年大规模爆发到现在,每年仍有大量实例中招。

事故是怎么发生的,通常四步:

  1. 攻击者用扫描器全网扫 6379 端口,找 PING 直接返回 PONG、不需要密码的实例。有安全团队做过统计,公网暴露的 Redis 往往在几小时内就会被扫到,不是「会不会」的问题。
  2. 连上之后不改数据,先改配置:CONFIG SET dir /var/spool/cron/crontabs、CONFIG SET dbfilename root,然后用 SET 写入一段带换行的内容,内容是定时任务,比如每分钟 curl 一个脚本并执行,最后 SAVE 把内存 dump 成 cron 文件。
  3. 定时任务被 cron 拉起,下载挖矿程序(常见的是 xmrig、kinsing 这类),同时杀掉其他挖矿进程、清理痕迹、加持久化。
  4. 更狠的玩法是 SLAVEOF 指向攻击者的恶意主库,同步一个带 MODULE LOAD 的 RDB 直接加载恶意模块执行系统命令;或者把公钥写进 /root/.ssh/authorized_keys 拿 SSH 登录。

中招后的现象:CPU 长期 100%、业务 RT 抖动、云厂商发短信说主机存在挖矿行为;也可能数据被 FLUSHALL 清空,只留一个要赎金的 key。等发现时,攻击者往往已经拿到了主机权限。

防守清单,按优先级排:

  • 永远不要把 6379 暴露到公网。安全组只放业务网段,bind 写内网地址,这是最有效的一条。
  • 必须设密码,32 位以上随机串,别用 123456、redis、公司名拼音。多应用共用就上 ACL 分账号。
  • protected-mode yes 保持默认开着,多一层兜底。
  • 不要用 root 跑 Redis。apt 包默认用 redis 用户,源码和容器部署要自己确认,容器别加 --privileged。
  • 限制危险命令。7.x 推荐用 ACL 收回 CONFIG、DEBUG、FLUSHALL、KEYS 权限;老办法 rename-command CONFIG "" 仍然可用,但会让一些运维工具失效,要评估。
  • 监控异常。关注 CONFIG GET dir 的调用、appendonlydir 之外的 dump 文件、/var/spool/cron 下的可疑文件,以及实例上突然出现的陌生 key。
# 快速自查:这三项应该是「有密码、只监听内网、保护模式开」
redis-cli CONFIG GET requirepass
redis-cli CONFIG GET bind
redis-cli CONFIG GET protected-mode

小结​

  • 三条安装路径:apt 快但版本旧,源码灵活但要自己写 systemd 单元,Docker 干净适合验证。
  • redis.conf 先盯四件事:bind、protected-mode、requirepass、daemonize,其余按需加。
  • 连接用 redis-cli -h -p -a,先 PING 验活,再 SET/GET 验读写;KEYS 只做演示,生产用 SCAN。
  • 无密码 + 公网监听 = 挖矿,这是时间问题不是概率问题;安全组、密码、非 root、ACL 四件套缺一不可。

环境跑通了,接下来进入命令层,看五种数据结构怎么用、事务和 Lua 怎么写,见下一篇《核心使用》。