13 10 月 2026

数据库扛不住时,加 Redis 缓存往往比升级服务器更有效——把频繁查询的结果放内存里,数据库压力能降 90%。

这篇讲 Redis 的安装、配置、安全加固、常用数据结构和实际应用方式。

Redis 是内存型数据库,内存要给够。财富云计算 提供多种规格云服务器;内部缓存服务、测试环境可选 NAT 型(无独立公网 IP,价格比带独立 IP 机型省一半以上)。

一、安装

# Debian/Ubuntu
apt update
apt install redis-server -y
systemctl enable --now redis-server

# CentOS/Rocky
yum install epel-release -y
yum install redis -y
systemctl enable --now redis

redis-cli ping        # 返回 PONG 说明正常
redis-server --version

二、必做的安全配置

Redis 未授权访问是最常见的被入侵原因之一(勒索软件最爱),务必做好这几点:

1)设置密码

nano /etc/redis/redis.conf
requirepass 你的强密码
systemctl restart redis-server
redis-cli -a 密码 ping

2)只监听本地或内网

bind 127.0.0.1        # 只本地
# 或
bind 127.0.0.1 10.0.0.5    # 本地 + 内网 IP

绝不要 bind 0.0.0.0 且无密码。

3)开启保护模式

protected-mode yes

4)防火墙不放行 6379 给公网

ufw deny 6379
ss -tulnp | grep 6379     # 确认只监听 127.0.0.1

5)禁用危险命令(可选但推荐)

rename-command FLUSHALL ""
rename-command FLUSHDB ""
rename-command CONFIG "随机字符串"
rename-command KEYS ""

防止误操作或被攻击者清空数据。

6)用普通用户运行

ps aux | grep redis     # 确认不是 root

三、核心配置参数

# /etc/redis/redis.conf

# 最大内存(重要!不设会用光系统内存)
maxmemory 512mb

# 内存满时的淘汰策略
maxmemory-policy allkeys-lru

# 持久化(RDB)
save 900 1          # 900 秒内至少 1 次改动就保存
save 300 10
save 60 10000
dbfilename dump.rdb
dir /var/lib/redis

# AOF(更强的持久性,按需开启)
appendonly no       # 缓存场景可关;需要持久化时设 yes
appendfsync everysec

# 日志
logfile /var/log/redis/redis-server.log
loglevel notice

# 安全
requirepass 密码
bind 127.0.0.1
protected-mode yes

内存淘汰策略

策略含义适用
noeviction内存满就报错(默认)数据不能丢
allkeys-lru淘汰最久未用的 key缓存场景推荐
volatile-lru只在设了过期时间的 key 里淘汰部分数据要常驻
allkeys-random随机淘汰
volatile-ttl淘汰剩余寿命最短的
allkeys-lfu淘汰使用频率最低的(Redis 4+)有热点数据时

缓存用途用 allkeys-lru。


四、数据结构与常用命令

1)String(字符串)

SET key "value"
SET key "value" EX 3600        # 1 小时过期
GET key
DEL key
EXISTS key
EXPIRE key 3600                # 设置过期时间
TTL key                        # 查看剩余秒数,-1 表示永不过期
INCR counter                   # 自增(计数器)
INCRBY counter 10
MSET k1 v1 k2 v2               # 批量设置
MGET k1 k2

2)Hash(哈希,适合存对象)

HSET user:1 name "张三" age 25
HGET user:1 name
HGETALL user:1
HDEL user:1 age
HINCRBY user:1 age 1

3)List(列表,队列/栈)

LPUSH queue task1
RPUSH queue task2
LPOP queue          # 从左边弹出
RPOP queue
LRANGE queue 0 -1   # 查看全部
LLEN queue

适合做简单消息队列。

4)Set(集合,去重)

SADD tags "php" "mysql"
SREM tags "php"
SMEMBERS tags
SISMEMBER tags "php"
SINTER set1 set2        # 交集

适合标签、共同好友、去重统计。

5)Sorted Set(有序集合,排行榜)

ZADD rank 100 "player1"
ZADD rank 200 "player2"
ZRANGE rank 0 -1 WITHSCORES      # 升序
ZREVRANGE rank 0 9 WITHSCORES    # Top 10
ZINCRBY rank 10 "player1"
ZSCORE rank "player1"

排行榜用这个,非常高效。

6)通用命令

KEYS pattern            # 查找 key(生产环境慎用,会阻塞)
SCAN 0 MATCH user:* COUNT 100    # 安全遍历(推荐)
DBSIZE                  # key 总数
FLUSHDB                 # 清空当前库
FLUSHALL                # 清空所有库
INFO                    # 服务器信息
INFO memory             # 内存信息
INFO stats              # 统计
CONFIG GET maxmemory
SLOWLOG GET 10          # 慢查询
MONITOR                 # 实时监控所有命令(调试用,别在生产开)

五、实际应用方式

1)缓存数据库查询结果

伪代码:

function getUser(id):
    key = "user:" + id
    data = redis.GET(key)
    if data != null:
        return data            # 缓存命中
    
    data = mysql.query("SELECT * FROM users WHERE id = ?", id)
    redis.SETEX(key, 3600, data)    # 缓存 1 小时
    return data

更新数据时删除缓存:

function updateUser(id, data):
    mysql.update(...)
    redis.DEL("user:" + id)     # 删缓存,下次读取会重新生成

2)缓存策略要点

缓存穿透(查不存在的 key,每次都打数据库):

// 数据库也没有时,缓存一个空值(短过期)
if (!$data) {
    $redis->setex($key, 60, '');
    return null;
}

缓存击穿(热点 key 过期瞬间,大量请求打到数据库):

// 用锁:只让一个请求去查数据库
$lock = $redis->set("lock:$key", 1, ['nx', 'ex' => 10]);
if ($lock) {
    // 查数据库,写缓存
} else {
    usleep(100000);    // 等一下再读缓存
    return $redis->get($key);
}

缓存雪崩(大量 key 同时过期):

// 过期时间加随机值
$ttl = 3600 + rand(0, 600);
$redis->setex($key, $ttl, $data);

3)Session 存储

PHP 配置:

; /etc/php/8.2/fpm/php.ini
session.save_handler = redis
session.save_path = "tcp://127.0.0.1:6379?auth=密码"

多台服务器共享 session,实现负载均衡下的登录态保持。

4)限流

function isAllowed(userId):
    key = "rate:" + userId
    count = redis.INCR(key)
    if count == 1:
        redis.EXPIRE(key, 60)      # 60 秒窗口
    return count <= 100            # 每分钟最多 100 次

5)排行榜

ZADD leaderboard score playerId
ZREVRANGE leaderboard 0 9 WITHSCORES     # Top 10

6)消息队列(简单场景)

LPUSH jobs jobData          # 生产者
BRPOP jobs 30               # 消费者(阻塞等待)

生产级应用建议用 RabbitMQ/Kafka,Redis 适合轻量场景。

7)分布式锁

SET lock:resource 随机值 NX EX 10     # 获取锁,10 秒自动释放
# 释放时要验证随机值(防止误删别人的锁)

六、持久化

RDB(快照)

save 900 1
save 300 10
save 60 10000

优点:文件小、恢复快。
缺点:可能丢最后一次快照后的数据。

redis-cli BGSAVE        # 手动触发后台保存
redis-cli LASTSAVE      # 查看上次保存时间

AOF(追加日志)

appendonly yes
appendfsync everysec     # 每秒同步(推荐)
# appendfsync always     # 每次写都同步(最安全最慢)

优点:数据丢失少。
缺点:文件大、恢复慢。

建议:

  • 纯缓存:可以都关(数据丢了从数据库重建)
  • 需要持久化:RDB + AOF 都开

备份

# 复制 RDB 文件
cp /var/lib/redis/dump.rdb /backup/redis-$(date +%F).rdb

# 或用 redis-cli
redis-cli --rdb /backup/dump.rdb

七、监控与排查

# 基本信息
redis-cli INFO

# 内存
redis-cli INFO memory | grep -E "used_memory_human|maxmemory_human|mem_fragmentation_ratio"

# 命中率(重要)
redis-cli INFO stats | grep -E "keyspace_hits|keyspace_misses"
# 命中率 = hits / (hits + misses),应 > 90%

# 连接数
redis-cli INFO clients

# 慢查询
redis-cli SLOWLOG GET 10

# 实时命令(调试用,别长期开)
redis-cli MONITOR

# 大 key 分析
redis-cli --bigkeys

# 延迟测试
redis-cli --latency

关键指标:

指标健康值
命中率> 90%(低了说明缓存没起作用)
内存使用< maxmemory 的 80%
连接数远低于 maxclients
碎片率(mem_fragmentation_ratio)1~1.5(过大说明碎片多)

八、性能优化

1)避免大 key

单个 key 存几 MB 会阻塞其他操作。

redis-cli --bigkeys      # 找出大 key

拆分:把大 Hash 拆成多个小 Hash。

2)避免 KEYS 命令

KEYS * 会遍历所有 key,数据量大时阻塞 Redis 几百毫秒。用 SCAN 代替。

3)使用批量命令

MSET k1 v1 k2 v2 k3 v3       # 比 3 次 SET 快
MGET k1 k2 k3
# 或用 pipeline

4)设置合理的过期时间

所有缓存 key 都要有过期时间,避免内存只增不减。

5)连接池

应用用连接池,避免频繁创建连接。


九、常见问题

问题原因解决
NOAUTH Authentication required需要密码redis-cli -a 密码
MISCONF Redis is configured to save RDB snapshots...持久化失败检查磁盘权限和空间
OOM command not allowed内存满且是 noeviction设 maxmemory-policy 或加内存
连不上只监听 127.0.0.1改 bind 或用本地连
数据丢失没开持久化 / 用了 FLUSHALL开持久化,禁用危险命令
响应慢有大 key / 用了 KEYS / 内存满用 --bigkeys 排查
被入侵(数据被清空、多了陌生 key)无密码且对外立即设密码 + 只监听本地
max number of clients reached连接数满调 maxclients,用连接池

被入侵的紧急处理

Redis 被未授权访问后,攻击者可能:

  • 清空数据勒索
  • 写入 SSH 公钥(~/.ssh/authorized_keys)
  • 写 crontab 挖矿
# 检查
cat ~/.ssh/authorized_keys      # 有没有陌生公钥
crontab -l                      # 有没有陌生任务
redis-cli KEYS *                # 有没有陌生 key

# 处理
redis-cli CONFIG SET requirepass 新密码
# 或立即停止 Redis,改配置后再启动

详见《服务器被入侵应急排查与处置》。


十、Redis vs Memcached

对比RedisMemcached
数据结构丰富(5 种)只有 key-value
持久化支持不支持
主从/集群支持需客户端实现
单线程/多线程单线程(6.0+ 多线程 IO)多线程
适用场景缓存、队列、排行榜、锁纯简单缓存

选 Redis 就对了,除非你只需要最简单的 KV 缓存且追求极致性能。


Redis 是提升网站性能性价比最高的手段之一。财富云计算 的云服务器支持按需配置内存,运行 Redis 很合适;内部缓存服务、测试环境可选 NAT 型(无独立公网 IP,价格比带独立 IP 机型省一半以上),Redis 只监听本地,既安全又省成本。

相关阅读:

  • 《MySQL 安装与优化入门》
  • 《网站打开慢的排查流程》
  • 《服务器安全基线检查清单》
延伸阅读
  1. 网站环境怎么选:LNMP 手动 / 宝塔面板 / Docker / 云开发
  2. 问卷表单系统搭建:SurveyKing / Formbricks,数据自己收
  3. 图床搭建:Lsky Pro / Lychee,自托管图片托管方案
  4. 邮件列表搭建:listmonk 自托管 Newsletter,把读者握在自己手里
  5. 文档站点搭建:MkDocs / VuePress / Docsify,产品文档与技术手册方案
  6. RSS 阅读器搭建:FreshRSS 自托管,把信息流拿回自己手里
  7. 短链接服务搭建:Shlink 自托管,链接数据自己掌握
  8. 网站状态监控页搭建:Uptime Kuma,服务器挂了第一时间知道
更多阅读
  1. 上一篇:MySQL 常见故障排查:连接爆满、慢查询、死锁、磁盘暴涨
  2. 下一篇:Docker 安装与基础命令:容器化部署入门
发表评论 4

取消回复