Redis on Kubernetes 面试题
30 道题- 分类
- 中间件
- 题目数
- 30 道
1 Redis 在 Kubernetes 上有哪些部署模式?各自适用场景是什么?
答案:
Redis 在 Kubernetes 上的部署模式分为三种:Standalone、Sentinel 和 Cluster。
| 部署模式 | 架构特征 | 高可用 | 数据分片 | 适用场景 |
|---|---|---|---|---|
| Standalone | 单实例 Deployment 或 StatefulSet | 无 | 无 | 开发测试、缓存场景(数据可丢失) |
| Sentinel | 一主多从 + Sentinel 哨兵集群 | 自动故障转移 | 无 | 读多写少、数据量在单机内存范围内 |
| Cluster | 多主多从、分片架构 | 自动故障转移 + 分片冗余 | 16384 个 Slot | 数据量超过单机内存、高吞吐写入 |
Standalone 以 Deployment 部署 Redis 单实例,无持久化,数据丢失可接受时最简单。
Sentinel 架构在 K8s 上通常以三个独立 Deployment 部署 Sentinel 进程,Redis 主从以 StatefulSet 部署,通过 Headless Service 实现 Pod 间互相发现。
Cluster 模式需为每个节点配置 cluster-announce-ip,依赖 StatefulSet + Headless Service 提供稳定网络标识,扩容时需手动执行 Slot 迁移命令。
2 Redis Sentinel 在 Kubernetes 上如何部署?自动故障转移流程是怎样的?
答案:
Sentinel 在 K8s 上的经典部署架构:
# Sentinel Deployment(3 副本)
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-sentinel
spec:
replicas: 3
selector:
matchLabels:
app: redis-sentinel
template:
spec:
containers:
- name: sentinel
image: redis:7.2
command: ["redis-sentinel"]
args: ["/etc/redis/sentinel.conf"]
ports:
- containerPort: 26379
Redis 主从以 StatefulSet 部署:
# Redis StatefulSet(3 副本:1 主 2 从)
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
spec:
serviceName: redis-headless
replicas: 3
selector:
matchLabels:
app: redis
template:
spec:
containers:
- name: redis
image: redis:7.2
command: ["redis-server"]
args: ["/etc/redis/redis.conf"]
ports:
- containerPort: 6379
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 50Gi
故障转移流程:
- Sentinel 通过 Headless Service(
redis-headless)发现所有 Redis Pod,持续PING检测 - 主观下线(SDOWN):单个 Sentinel 判定主节点不可达(
down-after-milliseconds超时) - 客观下线(ODOWN):超过
quorum数量的 Sentinel 确认主节点下线 - Sentinel Leader 选举:通过 Raft 协议选出执行故障转移的 Sentinel
- 从节点选举:按
slave-priority、复制偏移量、Run ID 排序选出新主 - 故障转移执行:新主执行
SLAVEOF NO ONE,其余从节点重定向到新主 - ConfigMap 更新:K8s 场景下 Sentinel 通过 ConfigMap 或 Operator 更新客户端连接信息
关键配置:
| 参数 | 说明 |
|---|---|
sentinel monitor mymaster <ip> <port> <quorum> | 监控主节点,quorum 设为 2 |
sentinel down-after-milliseconds mymaster 5000 | 主观下线判定超时 5 秒 |
sentinel failover-timeout mymaster 60000 | 故障转移超时 60 秒 |
sentinel parallel-syncs mymaster 1 | 故障转移后并行同步的从节点数 |
3 Redis Cluster 的分片机制与 16384 个 Slot 分配原理是什么?
答案:
Redis Cluster 采用 Hash Slot 机制实现数据分片,将键空间划分为 16384 个 Slot。
Slot 分配原理:
- 每个键通过
CRC16(key) % 16384计算所属 Slot - Slot 分布在多个主节点之间,每个主节点负责一段 Slot 范围
- 每个 Slot 可包含多个键,主节点负责其 Slot 范围内的所有读写操作
# 查看集群 Slot 分布
redis-cli cluster slots
# 手动分配 Slot
redis-cli --cluster add-node new-node:6379 existing-node:6379
redis-cli --cluster reshard <target-node>:6379
为什么是 16384?
| 维度 | 16384(16K) | 65536(64K) |
|---|---|---|
| 心跳消息大小 | 约 2KB(bitmap) | 约 8KB |
| 网络带宽占用 | 低(Gossip 协议 PING/PONG) | 高 |
| 节点数上限 | 建议 ≤ 1000 | 理论上更多 |
| Redis 设计权衡 | 足够用且消息体紧凑 | 带宽浪费 |
16384 是在心跳消息大小与节点扩展性之间的折中:16K 个 Slot 的 bitmap 仅需 2KB,在 Gossip 消息中传输效率高,且足以支撑 1000 个节点的集群规模。
4 Redis Cluster 的 Gossip 协议如何工作?
答案:
Redis Cluster 各节点通过 Gossip 协议 在 Cluster Bus(端口 16379,即 data_port + 10000)上交换集群元信息。
Gossip 通信机制:
- 每个节点每秒随机选取
cluster-node-timeout / 2个节点发送PING消息 - 收到
PING的节点回复PONG PING/PONG消息携带:- 发送者自身信息(node ID、IP、port、flags)
- 发送者已知的其他节点信息(Gossip 段)
- 当前纪元(currentEpoch)和配置纪元(configEpoch)
- 节点通过 Gossip 消息发现新节点,标记疑似故障节点(PFAIL -> FAIL)
关键参数:
| 参数 | 默认值 | 说明 |
|---|---|---|
cluster-node-timeout | 15000ms | 节点超时阈值,影响 PFAIL 判定 |
cluster-slave-validity-factor | 10 | 从节点故障转移有效性因子 |
cluster-migration-barrier | 1 | 从节点迁移屏障 |
K8s 场景注意事项:
- Cluster Bus 端口需在 Service 和 NetworkPolicy 中额外暴露
- Headless Service 需确保 Pod DNS 解析后 Cluster Bus 通信可达
cluster-announce-ip和cluster-announce-port需正确配置
5 Redis Cluster 节点扩缩容与 Slot 迁移如何执行?
答案:
扩容流程(添加新主节点):
# 1. 新节点加入集群
redis-cli --cluster add-node <new-node-ip>:6379 <existing-node-ip>:6379
# 2. 重新分配 Slot(在线迁移)
redis-cli --cluster reshard <target-node-ip>:6379 \
--cluster-from <source-node-id> \
--cluster-to <target-node-id> \
--cluster-slots <slot-count>
Slot 迁移内部流程:
- 目标节点执行
CLUSTER SETSLOT <slot> IMPORTING <source-node-id> - 源节点执行
CLUSTER SETSLOT <slot> MIGRATING <target-node-id> - 源节点执行
MIGRATE命令逐键迁移数据 - 迁移完成后通知集群所有节点更新 Slot 归属
- 源节点删除已迁移的键
# 添加从节点
redis-cli --cluster add-node <new-node-ip>:6379 <existing-node-ip>:6379 \
--cluster-slave --cluster-master-id <master-node-id>
# 删除节点
redis-cli --cluster del-node <node-ip>:6379 <node-id>
缩容流程:
- 将待下线节点的 Slot 迁移至其他节点(
--cluster reshard) - 确认 Slot 全部迁出后执行
--cluster del-node
K8s 上扩容:先 kubectl scale statefulset redis-cluster --replicas=N,再执行 redis-cli --cluster reshard 手动均衡 Slot。自动化方案依赖 Operator。
6 Redis Cluster 在 Kubernetes 上部署的核心挑战是什么?
答案:
| 挑战 | 说明 | 解决方案 |
|---|---|---|
| Pod IP 变化 | Pod 重启后 IP 变更,nodes.conf 中的节点地址失效 | 使用 StatefulSet + Headless Service 提供稳定 DNS 名;配置 cluster-announce-ip 为 Pod 域名 |
| Cluster Bus 通信 | 端口 16379(10000+6379)需路由可达 | Service 暴露 Cluster Bus 端口;NetworkPolicy 放行 TCP/16379 |
| 配置持久化 | nodes.conf 记录集群拓扑,Pod 重启后不能丢失 | 挂载 PVC 存储 nodes.conf;或使用 ConfigMap + Operator 管理 |
| Slot 迁移与 Pod 生命周期 | 直接 kubectl delete pod 会导致 Slot 丢失 | 缩容前先执行手动 Slot 迁移;使用 PDB 防止意外驱逐 |
| 客户端重定向 | Redis Cluster 返回 MOVED / ASK 错误,需客户端支持 | 客户端使用支持集群模式的驱动(JedisCluster、go-redis cluster) |
| 跨可用区延迟 | 跨区 Gossip 通信延迟可能触发误判 PFAIL | 增大 cluster-node-timeout;配置 cluster-require-full-coverage no |
配置示例:
# redis.conf
cluster-enabled yes
cluster-config-file /data/nodes.conf
cluster-node-timeout 15000
cluster-require-full-coverage no
cluster-announce-ip $(hostname).redis-cluster-headless.redis.svc.cluster.local
cluster-announce-port 6379
cluster-announce-bus-port 16379
7 Redis Operator 生态有哪些选择?各自优劣是什么?
答案:
| Operator | 维护方 | 功能特点 | 适用场景 |
|---|---|---|---|
| Redis Enterprise Operator | Redis Inc. | 商业版,支持 Active-Active、集群自动管理、GUI 运维 | 企业级生产环境,需要商业支持 |
| Spotahome Redis Operator | Spotahome | 开源,支持 Sentinel 和 Cluster 模式,自动故障转移 | 社区主流选择,中小规模集群 |
| Ot Redis Operator | OT-CONTAINER-KIT | 开源,支持 Cluster 和 Sentinel,Leader/Follower 模式 | 轻量级场景,K8s 原生集成 |
对比详情:
| 能力 | Redis Enterprise | Spotahome | Ot Operator |
|---|---|---|---|
| Sentinel 模式 | ✅ | ✅ | ✅ |
| Cluster 模式 | ✅ | ✅ | ✅ |
| 自动扩缩容 | ✅ | 手动 | 手动 |
| Active-Active 地理分布 | ✅ | ❌ | ❌ |
| 备份恢复 | ✅(内置 S3) | 手动 | 手动 |
| Prometheus 监控集成 | ✅ | ✅ | ✅ |
| 许可证 | 商业 | Apache 2.0 | Apache 2.0 |
| K8s CRD 管理 | 丰富 | 基础 | 基础 |
Spotahome 示例 CR:
apiVersion: databases.spotahome.com/v1
kind: RedisFailover
metadata:
name: redisfailover
spec:
sentinel:
replicas: 3
redis:
replicas: 3
storage:
persistentVolumeClaim:
metadata:
name: redis-data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 50Gi
8 Redis 持久化在 Kubernetes 上如何实现?
答案:
Redis 提供三种持久化策略,在 K8s 上均依赖 PVC 存储。
| 策略 | 机制 | 数据安全性 | 性能影响 | K8s 实现要点 |
|---|---|---|---|---|
| RDB | 定期全量内存快照 | 可能丢失最近几分钟数据 | 低(fork 子进程写入) | PVC 存储 /data/dump.rdb,save 参数控制触发频率 |
| AOF | 追加写日志 | 最多丢 1 秒数据(everysec) | 中(持续 IO 写入) | PVC 存储 /data/appendonly.aof,配合 aof-rewrite 控制文件增长 |
| RDB + AOF | 两者同时开启 | 高(AOF 优先于 RDB 加载) | 较高 | PVC 同时存储两种文件,恢复时优先使用 AOF |
| No Persistence | 纯内存 | 数据可丢失 | 最优 | 适用于纯缓存场景 |
RDB 配置:
save 900 1 # 900 秒内至少 1 个键变更
save 300 10 # 300 秒内至少 10 个键变更
save 60 10000 # 60 秒内至少 10000 个键变更
dbfilename dump.rdb
dir /data
AOF 配置:
appendonly yes
appendfsync everysec # 每秒同步一次(推荐)
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
K8s StatefulSet 持久化配置:
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "ssd-storage"
resources:
requests:
storage: 100Gi
性能考量:RDB fork 阶段内存翻倍风险,K8s 需配置 memory limit >= maxmemory * 2 或使用 redis-check-rdb 定期校验。AOF 写入需确保底层存储 IOPS 满足 appendfsync everysec 的延迟要求。
9 Redis 使用 StatefulSet 与 PVC 存储如何配置?
答案:
StatefulSet 为 Redis 提供稳定的网络标识和持久化存储,是生产部署的基础。
核心设计要点:
- ServiceName:绑定 Headless Service,生成稳定的 Pod DNS 名(
<pod-name>.<service-name>.<namespace>.svc.cluster.local) - volumeClaimTemplates:每个 Pod 自动创建独立 PVC,保证存储隔离
- Pod 顺序管理:
podManagementPolicy设为Parallel可并行启动(Sentinel/Cluster 场景) - 存储类选择:使用 SSD/high-IOPS StorageClass
完整配置:
# Headless Service
apiVersion: v1
kind: Service
metadata:
name: redis-headless
spec:
clusterIP: None
selector:
app: redis
ports:
- name: redis
port: 6379
- name: cluster-bus
port: 16379
# StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
spec:
serviceName: redis-headless
replicas: 6
podManagementPolicy: Parallel
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values: ["redis"]
topologyKey: kubernetes.io/hostname
containers:
- name: redis
image: redis:7.2
command: ["redis-server"]
args: ["/etc/redis/redis.conf"]
ports:
- containerPort: 6379
name: redis
- containerPort: 16379
name: cluster-bus
resources:
requests:
cpu: "2"
memory: 4Gi
limits:
cpu: "4"
memory: 8Gi
volumeMounts:
- name: data
mountPath: /data
- name: config
mountPath: /etc/redis
readinessProbe:
exec:
command: ["redis-cli", "ping"]
initialDelaySeconds: 10
periodSeconds: 5
livenessProbe:
exec:
command: ["redis-cli", "ping"]
initialDelaySeconds: 30
periodSeconds: 10
volumes:
- name: config
configMap:
name: redis-config
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "ssd-storage"
resources:
requests:
storage: 100Gi
10 Redis 备份与恢复在 Kubernetes 上如何实现?
答案:
备份策略:
| 方案 | 类型 | RPO | 实现方式 |
|---|---|---|---|
| RDB 快照 + S3 | 全量 | 分钟级 | CronJob 定时执行 BGSAVE,上传 dump.rdb 至 S3/MinIO |
| AOF 连续备份 | 增量 | 秒级 | sidecar 容器持续同步 /data/appendonly.aof 至对象存储 |
| 混合(RDB + AOF) | 全量 + 增量 | 秒级 | RDB 为基准备份,AOF 为增量补充 |
| Volume Snapshot | 存储层 | 取决于 CSI | 利用 CSI Snapshot 创建 PVC 快照 |
CronJob 备份示例:
apiVersion: batch/v1
kind: CronJob
metadata:
name: redis-backup
spec:
schedule: "0 */4 * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: backup
image: redis:7.2
env:
- name: S3_BUCKET
value: "redis-backups"
command:
- /bin/sh
- -c
- |
redis-cli -h redis-0.redis-headless BGSAVE
# 等待 BGSAVE 完成
while [ $(redis-cli -h redis-0.redis-headless INFO persistence | grep rdb_bgsave_in_progress | cut -d: -f2) -eq 1 ]; do
sleep 5
done
aws s3 cp /data/dump.rdb s3://$S3_BUCKET/redis-backup-$(date +%Y%m%d-%H%M).rdb
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
persistentVolumeClaim:
claimName: data-redis-0
restartPolicy: OnFailure
恢复流程:
- 从 S3 下载最新 RDB 文件至 PVC
- 恢复 AOF 文件(如有)至
/data/appendonly.aof - 启动 Redis,自动加载持久化文件
- 验证数据一致性:
redis-cli INFO keyspace - 切换流量至恢复后的实例
11 Redis 监控指标体系如何构建?
答案:
监控体系以 redis_exporter 为核心,通过 Prometheus 采集指标,Grafana 展示。
架构:
Redis Pod(sidecar: redis_exporter)
└── Prometheus(ServiceMonitor / PodMonitor)
└── Grafana Dashboard
└── AlertManager(告警规则)
核心指标分类:
| 类别 | 关键指标 | 阈值建议 |
|---|---|---|
| 连接 | redis_connected_clients、redis_rejected_connections | 连接数 > 80% maxclients |
| 内存 | redis_memory_used_bytes、redis_memory_max_bytes | used > 80% maxmemory |
| 命中率 | redis_keyspace_hits_total / (hits + misses) | 命中率 < 90% |
| 命令延迟 | redis_commands_duration_seconds | P99 > 10ms |
| 持久化 | redis_rdb_last_save_time_seconds | 最后保存 > 配置间隔 |
| 复制 | redis_master_repl_offset - redis_slave_repl_offset | 复制延迟 > 10MB |
| 集群 | redis_cluster_slots_ok / redis_cluster_slots_total | 不可用 Slot > 0 |
| 键过期 | redis_expired_keys_total、redis_evicted_keys_total | 驱逐率持续增长 |
Prometheus 告警规则示例:
groups:
- name: redis
rules:
- alert: RedisMemoryHigh
expr: redis_memory_used_bytes / redis_memory_max_bytes > 0.85
for: 5m
labels:
severity: warning
annotations:
summary: "Redis 内存使用率超过 85%"
- alert: RedisDown
expr: redis_up == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Redis 实例 XQOPEN $labels.instance XQCLOSE 不可达"
- alert: RedisReplicationLag
expr: (redis_master_repl_offset - redis_slave_repl_offset) > 10485760
for: 5m
labels:
severity: warning
annotations:
summary: "Redis 主从复制延迟超过 10MB"
12 Redis 慢查询日志与性能诊断如何进行?
答案:
慢查询日志记录执行时间超过阈值的命令。
# 配置慢查询
CONFIG SET slowlog-log-slower-than 10000 # 超过 10ms 记录
CONFIG SET slowlog-max-len 128 # 最多保留 128 条
# 查看慢查询
SLOWLOG GET 10 # 最近 10 条
SLOWLOG LEN # 总数
SLOWLOG RESET # 清空
性能诊断方法:
| 方法 | 用途 | 示例 |
|---|---|---|
SLOWLOG GET | 定位慢命令 | 识别 KEYS *、O(N) 命令 |
INFO commandstats | 命令调用统计 | 分析命令分布与耗时 |
redis-cli --latency | 网络延迟采样 | 判断网络瓶颈 |
redis-cli --latency-history | 延迟时间序列 | 检测延迟波动 |
redis-cli --bigkeys | 大 Key 扫描 | 发现内存热点 |
redis-cli --memkeys | 内存消耗排序 | 定位内存占用 |
MEMORY STATS | 内存使用详情 | 分析碎片率 |
redis-benchmark | 性能压测 | 基线测试 |
K8s 场景性能诊断清单:
- 检查 CPU Throttling(
container_cpu_cfs_throttled_seconds_total) - 检查内存是否触及 Limit 导致 OOM Kill
- 检查磁盘 IOPS 是否满足 AOF
appendfsync需求 - 检查网络延迟(
redis-cli --latency从应用 Pod 测试) - 检查 NUMA 亲和性与 CPU 绑定(
taskset)
13 Redis 内存管理策略有哪些?
答案:
maxmemory 与逐出策略:
maxmemory 4gb
maxmemory-policy allkeys-lru
| 逐出策略 | 行为 | 适用场景 |
|---|---|---|
noeviction | 不逐出,写操作返回错误 | 数据不允许丢失 |
volatile-lru | 从设置了 TTL 的键中 LRU 逐出 | 缓存 + 持久键混合 |
allkeys-lru | 所有键中 LRU 逐出 | 纯缓存场景 |
volatile-lfu | 设置了 TTL 的键中 LFU 逐出 | 热点数据保护 |
allkeys-lfu | 所有键中 LFU 逐出 | 访问频率敏感 |
volatile-random | 随机逐出设置了 TTL 的键 | 缓存淘汰均匀 |
allkeys-random | 随机逐出所有键 | 所有键同等重要 |
volatile-ttl | 优先逐出 TTL 短的键 | 按过期时间淘汰 |
内存碎片整理:
# 查看碎片率
INFO memory # mem_fragmentation_ratio
# 自动碎片整理(Redis 4.0+)
CONFIG SET activedefrag yes
CONFIG SET active-defrag-ignore-bytes 100mb
CONFIG SET active-defrag-threshold-lower 10 # 碎片率 > 1.1
mem_fragmentation_ratio = used_memory_rss / used_memory,大于 1.5 表示碎片严重。
K8s 内存管理注意:
resources.limits.memory需大于maxmemory,预留 fork RDB 和系统开销- 建议比例:
limits.memory >= maxmemory * 1.3 + 500MB - 开启
oom-score-adj避免 OOM Killer 误杀
14 Redis Pipeline 与 Batch 操作有什么不同?
答案:
| 维度 | Pipeline | Batch(MGET/MSET) | 事务(MULTI/EXEC) |
|---|---|---|---|
| 实现方式 | 客户端缓存多条命令一次性发送 | 单条命令操作多个 Key | 将多条命令打包原子执行 |
| 原子性 | 不保证 | 单个命令本身原子 | 保证(EXEC 前不被打断) |
| 网络往返 | 1 次 RTT(N 条命令) | 1 次 RTT(1 条命令) | 1 次 RTT(N 条命令) |
| 执行顺序 | 按发送顺序执行 | N/A | 按添加顺序执行 |
| 错误处理 | 某命令失败不影响其他 | 整体成功或失败 | 某命令语法错误时全部不执行 |
Pipeline 使用示例(Go):
pipe := rdb.Pipeline()
incr := pipe.Incr(ctx, "pipeline_counter")
pipe.Expire(ctx, "pipeline_counter", time.Hour)
cmds, err := pipe.Exec(ctx)
注意事项:
- Pipeline 内命令数量不宜过大,建议单次 ≤ 100 条
- Pipeline 不保证原子性,中间可能插入其他客户端的命令
- Redis Cluster 下 Pipeline 要求所有 Key 在同一个 Slot(可用
{}hash tag 控制)
15 Redis Pub/Sub 与 Stream 有什么区别?
答案:
| 维度 | Pub/Sub | Stream |
|---|---|---|
| 消息持久化 | 不持久,消费者不在线即丢失 | 持久化至内存/RDB/AOF |
| 消费者组 | 不支持 | 支持(XGROUP),可负载均衡 |
| 消息回溯 | 不支持 | 支持(按 ID 范围读取) |
| 消息确认 | 无 | 支持(XACK) |
| 适用场景 | 实时通知、聊天 | 事件溯源、消息队列、日志收集 |
| 内存管理 | 不堆积 | 需设置 MAXLEN 限制长度 |
Stream 基本操作:
# 写入
XADD mystream * field1 value1 field2 value2
# 读取(阻塞)
XREAD BLOCK 0 STREAMS mystream 0
# 消费者组
XGROUP CREATE mystream mygroup $ MKSTREAM
XREADGROUP GROUP mygroup consumer1 BLOCK 0 STREAMS mystream >
# 确认
XACK mystream mygroup <message-id>
# 限制长度
XADD mystream MAXLEN ~ 10000 * field value
K8s Stream 注意事项:
- Stream 数据存储在内存中,需注意
maxmemory限制 - 消费者组信息存储在 Redis 内存中,故障转移后需重建或持久化消费偏移
16 Redis 分布式锁方案有哪些?
答案:
| 方案 | 原理 | 安全性 | 适用场景 |
|---|---|---|---|
| SET NX + EX | SET key value NX EX <ttl> | 单实例安全 | 单机 Redis,低可靠性要求 |
| Redisson(RedLock) | 多数节点加锁成功视为获得锁 | 高(防脑裂) | 多节点 Redis,金融级场景 |
| SET + Lua 释放 | Lua 脚本原子校验 value 后删除 | 防误删 | 单实例需防锁被他人释放 |
SET NX 正确实现:
# 加锁
SET lock:order:123 unique-client-id NX EX 30
# 释放(Lua 脚本保证原子性)
EVAL "
if redis.call('GET', KEYS[1]) == ARGV[1] then
return redis.call('DEL', KEYS[1])
else
return 0
end
" 1 lock:order:123 unique-client-id
Redisson RedLock 原理:
- 客户端向 N 个独立 Redis 实例依次请求加锁
- 设置锁超时远小于 TTL(如 TTL=30s,超时=5ms)
- 当 ≥ N/2+1 个实例加锁成功,且总耗时 < TTL,锁获取成功
- 实际有效时间 = TTL - 获取耗时
- 释放时向所有实例发送释放命令
K8s 场景注意:RedLock 要求 Redis 实例彼此独立(不同节点、不同可用区),K8s 上需配合 podAntiAffinity 部署。
17 缓存穿透、击穿、雪崩如何防护?
答案:
| 问题 | 定义 | 防护方案 |
|---|---|---|
| 缓存穿透 | 查询不存在的数据,请求直达数据库 | 布隆过滤器、空值缓存(短 TTL)、参数校验 |
| 缓存击穿 | 热点 Key 过期瞬间高并发直达数据库 | 互斥锁(SET NX)、逻辑过期 + 异步刷新、永不过期 |
| 缓存雪崩 | 大量 Key 同时过期或 Redis 宕机 | TTL 随机化、多级缓存、限流降级、Redis 高可用 |
布隆过滤器(RedisBloom 模块):
# 添加元素
BF.ADD cache-filter "key:12345"
BF.EXISTS cache-filter "key:12345"
# 大规模导入
BF.RESERVE large-filter 0.01 1000000 # 错误率 1%,100 万容量
BF.MADD large-filter key1 key2 key3
热点 Key 互斥锁方案(伪代码):
func GetData(key string) (string, error) {
val, err := rdb.Get(ctx, key).Result()
if err == redis.Nil {
// 缓存未命中,使用互斥锁
lockKey := "lock:" + key
locked, _ := rdb.SetNX(ctx, lockKey, "1", 10*time.Second).Result()
if locked {
defer rdb.Del(ctx, lockKey)
val = queryDB(key)
rdb.Set(ctx, key, val, 30*time.Minute)
} else {
time.Sleep(100 * time.Millisecond)
return GetData(key) // 重试
}
}
return val, err
}
TTL 随机化:EXPIRE key <base_ttl + random(0, base_ttl * 0.3)>,避免集中过期。
18 大 Key 与热 Key 如何检测和处理?
答案:
检测手段:
| 工具 | 用途 | 命令 |
|---|---|---|
redis-cli --bigkeys | 扫描最大 Key | redis-cli -h <host> --bigkeys |
redis-cli --hotkeys | 扫描热 Key(需 maxmemory-policy 为 LFU) | redis-cli -h <host> --hotkeys |
MEMORY USAGE <key> | 精确计算 Key 内存占用 | MEMORY USAGE user:10001 |
OBJECT FREQ <key> | LFU 访问频率 | OBJECT FREQ user:10001 |
redis-rdb-tools | 离线分析 RDB 文件 | rdb -c memory dump.rdb |
SCAN + DEBUG OBJECT | 渐进式扫描 | SCAN 0 MATCH * COUNT 1000 |
大 Key 定义:
| 数据类型 | 阈值 |
|---|---|
| String | > 10MB |
| List / Set / ZSet / Hash | 元素数量 > 10000 |
| Stream | 消息数 > 100000 或总大小 > 50MB |
处理策略:
- 拆分:Hash 大 Key 按业务维度拆分为多个小 Hash
- 压缩:String 大 Key 先压缩再存储(snappy/gzip)
- 删除:分批渐进式删除,避免阻塞
# Hash 分批删除字段 HSCAN key 0 COUNT 100 → HDEL key field1 field2 ... - 迁移:使用
MIGRATE将单个大 Key 迁移至独立实例 - 架构调整:热 Key 前置本地缓存(如 Caffeine、BigCache)
19 Redis 客户端连接池如何配置?
答案:
连接池关键参数(以 go-redis 为例):
| 参数 | 说明 | 建议值 |
|---|---|---|
PoolSize | 最大连接数 | CPU 核数 × 4 ~ 10 |
MinIdleConns | 最小空闲连接 | PoolSize × 0.2 |
MaxIdleConns | 最大空闲连接 | PoolSize |
PoolTimeout | 等待连接超时 | 5s ~ 10s |
IdleTimeout | 空闲连接回收时间 | 5min |
IdleCheckFrequency | 空闲检查频率 | 1min |
ConnMaxLifetime | 连接最大生命周期 | 30min ~ 1h |
go-redis 配置示例:
rdb := redis.NewClient(&redis.Options{
Addr: "redis-headless:6379",
Password: os.Getenv("REDIS_PASSWORD"),
DB: 0,
PoolSize: 50,
MinIdleConns: 10,
MaxIdleConns: 50,
PoolTimeout: 5 * time.Second,
IdleTimeout: 5 * time.Minute,
DialTimeout: 5 * time.Second,
ReadTimeout: 3 * time.Second,
WriteTimeout: 3 * time.Second,
})
Redis 服务端连接参数:
maxclients 10000
timeout 300 # 空闲连接超时秒数
tcp-keepalive 60 # TCP keepalive 间隔
tcp-backlog 511 # TCP 完成队列大小
K8s 场景注意:
- 连接池大小需配合 Pod 副本数计算总连接数,不超过
maxclients - Service Mesh(如 Istio)的 sidecar 可能增加连接,需留余量
IdleTimeout应小于 Service/负载均衡的空闲超时,避免半开连接
20 Redis SSL/TLS 加密与 ACL 权限如何控制?
答案:
TLS 配置:
# redis.conf
tls-port 6380
port 0 # 禁用非 TLS 端口
tls-cert-file /etc/tls/tls.crt
tls-key-file /etc/tls/tls.key
tls-ca-cert-file /etc/tls/ca.crt
tls-auth-clients yes # 要求客户端证书
tls-protocols "TLSv1.2 TLSv1.3"
tls-ciphers DEFAULT:!MEDIUM
K8s cert-manager 集成:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: redis-tls
spec:
secretName: redis-tls-secret
duration: 2160h
renewBefore: 360h
dnsNames:
- "redis-0.redis-headless.redis.svc.cluster.local"
- "*.redis-headless.redis.svc.cluster.local"
issuerRef:
name: ca-issuer
kind: ClusterIssuer
ACL 权限控制(Redis 6.0+):
# 创建用户
ACL SETUSER reader on >password ~* +@read -@write -@dangerous
ACL SETUSER writer on >password ~* +@all -@dangerous
ACL SETUSER appuser on >password ~prefix:* +@all
# 查看用户
ACL LIST
ACL GETUSER reader
# 配置文件持久化
aclfile /etc/redis/users.acl
ACL 权限规则:
| 规则 | 含义 |
|---|---|
on / off | 启用/禁用用户 |
>password | 设置密码 |
~pattern | 可访问的键模式(~* 表示所有键) |
+@category | 授权命令类别(+@read 只读) |
-command | 禁用特定命令(-FLUSHALL) |
+command | 授权特定命令 |
21 Redis Read-Only Replica 读写分离如何实现?
答案:
配置从节点可读:
# 从节点配置
replica-read-only yes # 从节点只读(默认)
# 或
replica-read-only no # 允许写入(数据会被主节点覆盖)
客户端读写分离策略:
| 策略 | 原理 | 一致性 |
|---|---|---|
| 应用层路由 | 客户端维护主从连接,写操作用主连接,读操作用从连接 | 最终一致(存在复制延迟) |
| Proxy 层 | Proxy 解析命令类型自动路由(如 Twemproxy、Codis) | 最终一致 |
| 一致性读 | 写后紧接的读强制走主节点 | 强一致 |
go-redis 读写分离示例:
// 主节点(写入)
master := redis.NewClient(&redis.Options{
Addr: "redis-master:6379",
})
// 从节点(读取)
slaves := redis.NewRing(&redis.RingOptions{
Addrs: map[string]string{
"slave0": "redis-slave-0.redis-headless:6379",
"slave1": "redis-slave-1.redis-headless:6379",
},
})
// 业务代码
master.Set(ctx, "key", "value", 0)
slaves.Get(ctx, "key")
一致性边界:Redis 主从复制是异步的,读从可能读到旧数据。需要强一致性的读操作必须走主节点。可通过 WAIT 命令将异步复制变为半同步:
SET key value
WAIT 1 1000 # 等待至少 1 个从节点确认,超时 1000ms
22 Redis 在线迁移方案有哪些?
答案:
| 方案 | 原理 | 停机时间 | 适用场景 |
|---|---|---|---|
| Redis-Shake | 解析 RDB + AOF,全量 + 增量同步 | 秒级(切换瞬间) | 跨集群迁移、云上云下迁移 |
| 主从复制切换 | 新实例 REPLICAOF 旧主,同步后切换 | 秒级 | 同版本升级、迁移 |
| RDB 导入 | BGSAVE → 拷贝 RDB → 新实例加载 | 分钟级 | 停机维护窗口 |
| MIGRATE | 单 Key 原子迁移 | 无(逐 Key) | 集群 Slot 迁移 |
| SCAN + DUMP/RESTORE | 分批序列化传输 | 无(逐批) | 选择性数据迁移 |
Redis-Shake 迁移流程:
# Redis-Shake K8s Job
apiVersion: batch/v1
kind: Job
metadata:
name: redis-shake-migration
spec:
template:
spec:
containers:
- name: redis-shake
image: apsaradb/redis-shake:latest
command:
- redis-shake.linux
args:
- -type=sync # sync / restore / scan
- -conf=/etc/shake.toml
volumeMounts:
- name: config
mountPath: /etc
volumes:
- name: config
configMap:
name: redis-shake-config
restartPolicy: Never
shak.toml 配置:
[sync_reader]
address = "source-redis:6379"
password = "source-pwd"
[redis_writer]
address = "target-redis:6379"
password = "target-pwd"
迁移步骤:
- 部署 Redis-Shake 同步任务
- 等待全量 + 增量追平(延迟 < 1ms)
- 停止源端写入
- 确认数据一致后切换客户端连接至目标
- 停止 Redis-Shake,清理源实例
23 Redis 拓扑感知调度如何通过 Pod Anti-Affinity 实现?
答案:
Pod Anti-Affinity 确保 Redis 实例分散在不同节点 / 可用区,避免单点故障。
三层调度策略:
| 策略级别 | topologyKey | 效果 |
|---|---|---|
| 节点级反亲和 | kubernetes.io/hostname | 同节点不部署多个 Redis Pod |
| 可用区级反亲和 | topology.kubernetes.io/zone | 同可用区最多一个副本 |
| 软反亲和 | preferredDuringScheduling | 优先分散,资源不足时可堆叠 |
完整配置:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values: ["redis"]
topologyKey: kubernetes.io/hostname
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-role.kubernetes.io/redis
operator: Exists
TopologySpreadConstraints(替代 Anti-Affinity):
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: redis
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app: redis
Node Selector / Taint-Toleration:Redis Pod 专属节点池,通过 taint 隔离其他工作负载:
tolerations:
- key: "dedicated"
operator: "Equal"
value: "redis"
effect: "NoSchedule"
nodeSelector:
node-group: redis
24 Redis Lua 脚本与事务有什么区别?
答案:
| 维度 | Lua 脚本 | MULTI/EXEC 事务 | WATCH 乐观锁 |
|---|---|---|---|
| 原子性 | 完全原子,执行期间不可中断 | 命令打包,但不回滚 | 不保证原子性 |
| 条件逻辑 | 支持(if/else/循环) | 不支持(命令固定) | 支持 CAS |
| 网络往返 | 1 次 | 1 次 | 多次 |
| 错误处理 | 脚本执行失败不回滚已执行部分 | 语法错误全部不执行,运行时错误不回滚 | 竞争失败需重试 |
Lua 脚本示例:
-- 分布式限流:令牌桶
local key = KEYS[1]
local capacity = tonumber(ARGV[1])
local rate = tonumber(ARGV[2])
local now = tonumber(ARGV[3])
local tokens = tonumber(redis.call('HGET', key, 'tokens')) or capacity
local last_time = tonumber(redis.call('HGET', key, 'last_time')) or now
local delta = math.max(0, now - last_time)
local new_tokens = math.min(capacity, tokens + delta * rate)
if new_tokens >= 1 then
redis.call('HSET', key, 'tokens', new_tokens - 1)
redis.call('HSET', key, 'last_time', now)
return 1
else
redis.call('HSET', key, 'tokens', new_tokens)
redis.call('HSET', key, 'last_time', now)
return 0
end
EVAL "<script>" 1 "rate_limit:user:123" 10 0.5 <current_timestamp>
WATCH 乐观锁:
WATCH balance:user:100
val = GET balance:user:100
MULTI
SET balance:user:100 <val - amount>
EXEC # 如果 key 被修改,EXEC 返回 nil
25 RedisJSON、RedisSearch、RedisTimeSeries 模块有何用途?
答案:
| 模块 | 用途 | 核心命令 | K8s 部署方式 |
|---|---|---|---|
| RedisJSON | JSON 文档存储与查询 | JSON.SET、JSON.GET、JSON.ARRAPPEND | redislabs/rejson 镜像 |
| RedisSearch | 全文搜索、向量搜索 | FT.CREATE、FT.SEARCH、FT.AGGREGATE | redislabs/redisearch 镜像 |
| RedisTimeSeries | 时序数据存储与聚合 | TS.CREATE、TS.ADD、TS.RANGE | redislabs/redistimeseries 镜像 |
| RedisBloom | 布隆过滤器、计数、布谷鸟 | BF.ADD、CF.ADD、CMS.INCRBY | redislabs/rebloom 镜像 |
| RedisGraph | 图数据库 | GRAPH.QUERY | redislabs/redisgraph 镜像 |
模块加载方式:
# redis.conf
loadmodule /usr/lib/redis/modules/redisearch.so
loadmodule /usr/lib/redis/modules/rejson.so
loadmodule /usr/lib/redis/modules/redistimeseries.so
Redis Stack 镜像(一站式):
containers:
- name: redis
image: redis/redis-stack-server:7.2.0-v10
# 已内置 RedisJSON、RedisSearch、RedisTimeSeries、RedisBloom、RedisGraph
RedisSearch 全文搜索:
FT.CREATE idx:articles ON JSON PREFIX 1 article: SCHEMA \
$.title AS title TEXT SORTABLE \
$.content AS content TEXT \
$.tags.* AS tags TAG
FT.SEARCH idx:articles "@title:kubernetes @tags:{redis}" RETURN 2 title tags
RedisTimeSeries 时序聚合:
TS.CREATE ts:sensor:temp RETENTION 86400000 LABELS sensor_id 1
TS.ADD ts:sensor:temp * 23.5
TS.RANGE ts:sensor:temp <start> <end> AGGREGATION avg 60000 # 1 分钟均值
26 PodDisruptionBudget 如何保障 Redis 在节点维护时的高可用?
答案:
PodDisruptionBudget(PDB) 限制同时不可用的 Pod 数量,防止节点维护或集群自动缩放时批量驱逐 Redis Pod。
PDB 配置:
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: redis-pdb
spec:
maxUnavailable: 1 # Sentinel:最多 1 个 Pod 不可用
selector:
matchLabels:
app: redis
# Cluster 模式:每个 StatefulSet 至少保留 N-1 个可用
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: redis-cluster-pdb
spec:
minAvailable: 5 # 6 节点集群至少保持 5 个可用
selector:
matchLabels:
app: redis-cluster
PDB 与故障转移联动:
kubectl drain <node>触发 Pod 驱逐- PDB 限制同时驱逐数量
- 驱逐的 Pod 如果是主节点,Sentinel 触发故障转移
- 从节点提升为新主后,流量切换到新主
- 被驱逐的 Pod 在新节点重新调度
多重保障策略:
| 保障手段 | 作用 |
|---|---|
| PDB | 限制驱逐数量,防止集群大规模不可用 |
| Pod Anti-Affinity | 分散在不同节点,降低同时被驱逐风险 |
| Pod Priority | Redis Pod 优先级高于普通 Pod,避免被优先驱逐 |
terminationGracePeriodSeconds | 足够时间(≥ 60s)完成 BGSAVE 持久化 |
27 Redis 跨集群复制与灾备如何实现?
答案:
| 方案 | 同步方式 | RPO | RTO | 适用场景 |
|---|---|---|---|---|
| 异地从节点 | 异步复制(REPLICAOF) | 秒级 | 分钟级 | 同地域跨可用区 |
| 双写 | 应用层同时写两个集群 | 取决于应用实现 | 秒级 | 最终一致性容忍场景 |
| Redis-Shake 持续同步 | RDB + AOF 解析同步 | 秒级 | 分钟级 | 跨云迁移、异地灾备 |
| Redis Enterprise Active-Active | CRDT 冲突解决 | 毫秒级 | 秒级 | 全球分布式,需要商业许可 |
| RDB 定时备份 + 异地恢复 | 全量备份 + S3 同步 | 小时级 | 30 分钟+ | 低成本灾备 |
异地从节点配置:
# 灾备集群从节点
REPLICAOF <primary-cluster-master-ip> 6379
Redis-Shake 灾备同步(持续模式):
[sync_reader]
address = "primary-cluster-redis:6379"
[redis_writer]
address = "dr-cluster-redis:6379"
[advanced]
dir = /data
ncpu = 4
灾备演练流程:
- 停止源集群写入
- 确认灾备集群数据同步完成(对比
master_repl_offset) - 灾备集群从节点执行
REPLICAOF NO ONE提升为主 - DNS/Service 切换流量至灾备集群
- 验证业务功能完整性
- 数据反向同步:灾备 → 原集群恢复后回流
28 Redis vs KeyDB vs Dragonfly 对比
答案:
| 维度 | Redis 7.2 | KeyDB | Dragonfly |
|---|---|---|---|
| 架构 | 单线程事件循环(I/O 多线程) | 多线程(真正的并行处理) | 多线程(无共享架构) |
| 线程模型 | 1 个主线程 + I/O 线程(6.0+) | N 个工作线程并行执行命令 | 分片 + 事务引擎 |
| 性能 | ~100K QPS(单核) | ~500K QPS(多核) | ~1M+ QPS(多核) |
| 兼容性 | Redis 原生协议 | Redis 协议完全兼容 | Redis 协议兼容(部分命令不支持) |
| 内存效率 | 基准 | 与 Redis 相当 | 比 Redis 节省 30%+ 内存(DashTable) |
| 持久化 | RDB + AOF | RDB + AOF | 自定义快照格式 |
| 集群 | Redis Cluster(原生) | Active Replication(多主) | 1.0+ 支持集群 |
| Lua 脚本 | 完全支持 | 完全支持 | 有限支持(无 EVAL) |
| 模块 | RedisJSON/Search/TS/Bloom/Graph | 部分支持 | 不支持原生模块 |
| K8s 部署 | 成熟(多个 Operator) | 社区支持 | 官方 Helm Chart |
| 许可证 | RSALv2 / SSPLv1 | BSD 3-Clause | BSL(Business Source License) |
| 适用场景 | 通用缓存/队列/会话 | 多核高吞吐缓存 | 大内存成本敏感场景 |
选型建议:
- Redis:生态最成熟,模块丰富,企业级支持,K8s Operator 完善
- KeyDB:需要多线程并行处理的纯缓存场景,Redis 协议无缝迁移
- Dragonfly:内存成本敏感,不需要 Redis 模块,追求极致吞吐
29 Redis on Kubernetes 常见故障排查
答案:
| 故障现象 | 可能原因 | 排查步骤 | 解决方案 |
|---|---|---|---|
| OOM Kill | 内存超出 Limit | kubectl describe pod 查看 OOMKilled;检查 maxmemory 配置 | 增加 resources.limits.memory;降低 maxmemory;启用逐出策略 |
| CPU Throttling | CPU Limit 过低 | 检查 container_cpu_cfs_throttled 指标 | 提高 CPU Limit 或使用 Guaranteed QoS |
| 启动失败 | RDB/AOF 损坏 | redis-check-rdb /data/dump.rdb;redis-check-aof /data/appendonly.aof | 修复或删除损坏文件重新启动 |
| 复制延迟 | 网络带宽不足、主写入量大 | INFO replication 查看 master_repl_offset - slave_repl_offset | 增大网络带宽;使用 repl-diskless-sync |
| 脑裂 | Sentinel quorum 不满足;网络分区 | 检查 Sentinel 日志;SENTINEL MASTER mymaster | 调整 quorum 为 N/2+1;配置 min-slaves-to-write |
| 集群状态 fail | 主节点宕机且无从节点接管 Slot | CLUSTER INFO 查看 cluster_state | 修复故障节点;CLUSTER FAILOVER 手动切换 |
| 磁盘空间满 | RDB/AOF 文件增长过大 | df -h /data | 调整 auto-aof-rewrite-min-size;扩展 PVC |
| 客户端连接泄漏 | 未正确关闭连接 | CLIENT LIST 查看连接数增长 | 应用端 Connection Pool 设置 MaxLifetime |
| Pod 无法调度 | PDB + Anti-Affinity 冲突 | kubectl describe pod 查看 Events | 调整 PDB minAvailable;增加节点 |
| 慢查询阻塞 | KEYS *、O(N) 命令 | SLOWLOG GET 10 | 替换为 SCAN;RENAME 禁用危险命令 |
排查常用命令:
# K8s 侧
kubectl describe pod redis-0
kubectl logs redis-0 -c redis --tail=200
kubectl exec -it redis-0 -- redis-cli INFO
kubectl exec -it redis-0 -- redis-cli CLUSTER INFO
kubectl get events --field-selector involvedObject.name=redis-0
# Redis 侧
redis-cli INFO all
redis-cli CLUSTER NODES
redis-cli SLOWLOG GET 20
redis-cli CLIENT LIST
redis-cli MEMORY STATS
redis-cli --latency -h <host>
30 Redis on Kubernetes 生产环境最佳实践总结
答案:
部署架构:
- 使用 StatefulSet 而非 Deployment,保障稳定的网络标识和持久化存储
- 配置 Headless Service(
clusterIP: None),为每个 Pod 提供独立 DNS 记录 - 设置 Pod Anti-Affinity 确保 Redis 实例分散在不同节点 / 可用区
- 使用 Operator(Spotahome / Ot Operator)管理 Sentinel 或 Cluster 拓扑,减少运维复杂度
- 配置 PodDisruptionBudget 防止节点维护时批量驱逐
资源配置:
resources.limits.memory >= maxmemory * 1.5,为 RDB fork 和系统开销留余量resources.requests.memory = resources.limits.memory(Guaranteed QoS),避免被 OOM Killresources.requests.cpu >= 2,生产环境不共享 CPU- 使用 SSD / NVMe StorageClass 且 IOPS >= 3000
- PVC 大小按
maxmemory * 1.5(RDB)或maxmemory * 3(AOF)预估
高可用与可靠性:
- Sentinel 部署 3 个或 5 个(奇数),quorum = N/2 + 1
- 配置
min-replicas-to-write 1和min-replicas-max-lag 10,防止主节点脑裂后写入丢失 - Cluster 模式每个主节点至少配 1 个从节点,跨可用区分布
- 配置
cluster-require-full-coverage no,允许部分 Slot 不可用时集群继续服务 - 定期执行备份演练和故障转移演练
持久化与备份:
- 生产环境开启 AOF(
everysec)+ RDB 混合持久化 - 配置
auto-aof-rewrite-percentage 100和auto-aof-rewrite-min-size 64mb - 使用 CronJob 定时执行 RDB 备份并上传至对象存储(S3/MinIO)
- 定期执行
redis-check-rdb和redis-check-aof验证备份文件完整性 - 备份数据跨区域复制(S3 Cross-Region Replication)
安全:
- 为每个应用创建独立 ACL 用户,最小权限原则(
+@read -@write -@dangerous) - 启用 TLS 加密通信(
tls-port),使用 cert-manager 自动管理证书 - 重命名或禁用危险命令:
rename-command FLUSHALL ""、rename-command CONFIG "" - 配置
protected-mode yes和bind限制访问网段 - 不暴露 Redis 端口至公网,使用 NetworkPolicy 限制入站流量
监控与告警:
- 部署
redis_exporter作为 Sidecar 容器,通过 Prometheus PodMonitor 采集指标 - 配置关键告警:内存 > 80%、连接数 > 80%、命中率 < 90%、复制延迟 > 10MB
- 使用 Grafana Dashboard(如 763)集中展示 Redis 集群状态
- 集成日志采集(Filebeat/Fluentd → Elasticsearch/Loki),结构化解析 Redis 日志
- 设置慢查询告警:
SLOWLOG增长速率异常时触发通知