Files
juwan-backend/docs/redis-services-guide.md
T

1180 lines
26 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Redis Services 连接指南
**环境:** juwan namespace
**Redis 版本:** 7.0.12
**部署模式:** RedisReplication + RedisSentinel
**文档日期:** 2026年2月22日
---
## 📋 目录
1. [Service 列表总览](#service-列表总览)
2. [Redis 数据层 Service 详解](#redis-数据层-service-详解)
3. [Sentinel 监控层 Service 详解](#sentinel-监控层-service-详解)
4. [管理工具连接方式](#管理工具连接方式)
5. [应用服务连接方式](#应用服务连接方式)
6. [连接方式对比](#连接方式对比)
7. [最佳实践建议](#最佳实践建议)
8. [故障排查](#故障排查)
---
## 📊 Service 列表总览
当前集群中部署的 Redis 相关 Service
| Service 名称 | 类型 | Cluster IP | 端口 | 用途 |
|-------------|------|-----------|------|------|
| **user-redis** | ClusterIP | 10.103.91.84 | 6379, 9121 | 通用访问 + 监控 |
| **user-redis-additional** | ClusterIP | 10.107.228.48 | 6379 | 额外访问入口 |
| **user-redis-headless** | ClusterIP(None) | None | 6379 | Pod 间直接访问 |
| **user-redis-master** ⭐ | ClusterIP | 10.97.120.76 | 6379 | 主节点访问 |
| **user-redis-replica** ⭐ | ClusterIP | 10.100.213.103 | 6379 | 从节点访问 |
| **user-redis-sentinel-sentinel** ⭐⭐⭐ | ClusterIP | 10.105.28.231 | 26379 | Sentinel 访问 |
| **user-redis-sentinel-sentinel-additional** | ClusterIP | 10.97.111.42 | 26379 | 额外 Sentinel 入口 |
| **user-redis-sentinel-sentinel-headless** | ClusterIP(None) | None | 26379 | Sentinel 间通信 |
**图例:**
- ⭐⭐⭐ 生产环境强烈推荐
- ⭐ 生产环境可用
- 无标记:特殊场景或内部使用
---
## 🔴 Redis 数据层 Service 详解
### 1. user-redis-master ⭐
**基本信息**
```yaml
名称: user-redis-master
类型: ClusterIP
IP: 10.97.120.76
端口: 6379/TCP
DNS: user-redis-master.juwan.svc.cluster.local
```
**功能特点**
- 🎯 自动追踪当前 Redis 主节点
- ✅ 确保所有写操作到达主节点
- 🔄 故障转移后自动指向新主节点
- 💪 提供最强一致性保证
**适用场景**
- ✅ 所有写操作(SET, HSET, ZADD 等)
- ✅ 需要强一致性的读操作
- ✅ 事务操作(MULTI/EXEC
- ❌ 不适合高并发读请求
**连接示例**
```go
// Go - go-redis
rdb := redis.NewClient(&redis.Options{
Addr: "user-redis-master.juwan.svc.cluster.local:6379",
Password: os.Getenv("REDIS_PASSWORD"),
DB: 0,
})
// 写操作
err := rdb.Set(ctx, "user:1001", "John Doe", 0).Err()
```
```bash
# CLI 测试
kubectl run -it --rm redis-cli --image=redis:7.0.12 --restart=Never -n juwan -- \
redis-cli -h user-redis-master -a <password> SET test "hello"
```
---
### 2. user-redis-replica ⭐
**基本信息**
```yaml
名称: user-redis-replica
类型: ClusterIP
IP: 10.100.213.103
端口: 6379/TCP
DNS: user-redis-replica.juwan.svc.cluster.local
```
**功能特点**
- 📖 负载均衡到所有从节点(当前 2 个)
- ⚡ 分散读请求,提升吞吐量
- 🕐 可能存在轻微的复制延迟(通常 < 100ms)
- 🚫 只读模式,写操作会失败
**适用场景**
- ✅ 高并发读请求
- ✅ 查询操作(GET, HGET, ZRANGE 等)
- ✅ 统计分析类查询
- ⚠️ 对数据实时性要求不高的场景
- ❌ 不能用于写操作
**连接示例**
```go
// Go - 读写分离配置
masterClient := redis.NewClient(&redis.Options{
Addr: "user-redis-master.juwan.svc.cluster.local:6379",
Password: os.Getenv("REDIS_PASSWORD"),
})
replicaClient := redis.NewClient(&redis.Options{
Addr: "user-redis-replica.juwan.svc.cluster.local:6379",
Password: os.Getenv("REDIS_PASSWORD"),
ReadOnly: true,
})
// 写操作用 master
masterClient.Set(ctx, "counter", 100, 0)
// 读操作用 replica
val, err := replicaClient.Get(ctx, "counter").Result()
```
---
### 3. user-redis
**基本信息**
```yaml
名称: user-redis
类型: ClusterIP
IP: 10.103.91.84
端口: 6379/TCP (Redis), 9121/TCP (Exporter)
DNS: user-redis.juwan.svc.cluster.local
```
**功能特点**
- 🔀 负载均衡到所有 Redis 节点(主 + 从)
- 📊 端口 9121 暴露 Prometheus 指标
- ⚠️ 写操作可能路由到从节点导致失败
**适用场景**
- ✅ Prometheus 监控抓取(端口 9121
- ⚠️ 测试环境的简单访问
- ❌ 不推荐生产环境读写操作
**监控配置**
```yaml
# Prometheus ServiceMonitor
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: redis-metrics
namespace: juwan
spec:
selector:
matchLabels:
app: redis
endpoints:
- port: redis-exporter
interval: 30s
path: /metrics
```
---
### 4. user-redis-additional
**基本信息**
```yaml
名称: user-redis-additional
类型: ClusterIP
IP: 10.107.228.48
端口: 6379/TCP
```
**功能特点**
- 功能类似 user-redis
- 提供额外的访问入口
- 用于多租户或网络隔离场景
**适用场景**
- 特殊网络策略场景
- 多应用隔离访问
- 备用访问点
---
### 5. user-redis-headless
**基本信息**
```yaml
名称: user-redis-headless
类型: ClusterIP (Headless - None)
端口: 6379/TCP
DNS:
- user-redis-0.user-redis-headless.juwan.svc.cluster.local
- user-redis-1.user-redis-headless.juwan.svc.cluster.local
- user-redis-2.user-redis-headless.juwan.svc.cluster.local
```
**功能特点**
- 🎯 直接返回所有 Pod IP,不做负载均衡
- 🔗 用于 StatefulSet Pod 间通信
- 📡 Redis 主从复制使用此服务发现
**适用场景**
- ✅ 内部复制通信
- ✅ 集群管理操作
- ✅ 需要直接访问特定 Pod
- ❌ 不适合应用层使用
**直接访问示例**
```bash
# 直接连接 user-redis-0
redis-cli -h user-redis-0.user-redis-headless.juwan.svc.cluster.local -a <password>
# DNS 解析会返回具体 Pod IP
nslookup user-redis-headless.juwan.svc.cluster.local
```
---
## 🟡 Sentinel 监控层 Service 详解
### 1. user-redis-sentinel-sentinel ⭐⭐⭐
**基本信息**
```yaml
名称: user-redis-sentinel-sentinel
类型: ClusterIP
IP: 10.105.28.231
端口: 26379/TCP
DNS: user-redis-sentinel-sentinel.juwan.svc.cluster.local
```
**功能特点**
- 🛡️ 提供高可用 Redis 访问
- 🔄 自动发现主节点
- ⚡ 主节点故障时自动切换
- 📍 客户端自动跟踪主节点变化
**Sentinel 架构**
```
应用 → Sentinel Service → Sentinel 节点 (3个)
监控 Redis 集群
自动发现当前主节点位置
```
**适用场景**
- ✅✅✅ **生产环境强烈推荐**
- ✅ 需要自动故障转移
- ✅ 高可用架构
- ✅ 无需手动处理主从切换
**连接示例**
```go
// Go - go-redis Sentinel 模式
rdb := redis.NewFailoverClient(&redis.FailoverOptions{
MasterName: "mymaster",
SentinelAddrs: []string{
"user-redis-sentinel-sentinel.juwan.svc.cluster.local:26379",
},
Password: os.Getenv("REDIS_PASSWORD"),
DB: 0,
// 连接池配置
PoolSize: 10,
MinIdleConns: 5,
// 超时配置
DialTimeout: 5 * time.Second,
ReadTimeout: 3 * time.Second,
WriteTimeout: 3 * time.Second,
})
// 使用方式与普通客户端完全一致
err := rdb.Set(ctx, "key", "value", 0).Err()
val, err := rdb.Get(ctx, "key").Result()
```
```python
# Python - redis-py Sentinel 模式
from redis.sentinel import Sentinel
sentinel = Sentinel([
('user-redis-sentinel-sentinel.juwan.svc.cluster.local', 26379)
], socket_timeout=0.5)
# 获取主节点(写)
master = sentinel.master_for('mymaster',
password=os.getenv('REDIS_PASSWORD'),
socket_timeout=0.5)
master.set('key', 'value')
# 获取从节点(读)
slave = sentinel.slave_for('mymaster',
password=os.getenv('REDIS_PASSWORD'),
socket_timeout=0.5)
value = slave.get('key')
```
```yaml
# Spring Boot application.yml
spring:
redis:
sentinel:
master: mymaster
nodes:
- user-redis-sentinel-sentinel.juwan.svc.cluster.local:26379
password: ${REDIS_PASSWORD}
```
**Sentinel 命令查询**
```bash
# 查看主节点信息
kubectl exec -it user-redis-sentinel-sentinel-0 -n juwan -- \
redis-cli -p 26379 SENTINEL get-master-addr-by-name mymaster
# 查看所有监控的主节点
kubectl exec -it user-redis-sentinel-sentinel-0 -n juwan -- \
redis-cli -p 26379 SENTINEL masters
# 查看从节点列表
kubectl exec -it user-redis-sentinel-sentinel-0 -n juwan -- \
redis-cli -p 26379 SENTINEL slaves mymaster
# 查看 Sentinel 节点
kubectl exec -it user-redis-sentinel-sentinel-0 -n juwan -- \
redis-cli -p 26379 SENTINEL sentinels mymaster
```
---
### 2. user-redis-sentinel-sentinel-additional
**基本信息**
```yaml
名称: user-redis-sentinel-sentinel-additional
类型: ClusterIP
IP: 10.97.111.42
端口: 26379/TCP
```
**功能特点**
- 功能同 user-redis-sentinel-sentinel
- 提供额外访问入口
- 用于多客户端分离
**适用场景**
- 多应用共享 Redis 时的访问隔离
- 网络策略要求
- 流量分离
---
### 3. user-redis-sentinel-sentinel-headless
**基本信息**
```yaml
名称: user-redis-sentinel-sentinel-headless
类型: ClusterIP (Headless - None)
端口: 26379/TCP
```
**功能特点**
- Sentinel 节点间通信
- 选举和投票
- 状态同步
**适用场景**
- 内部使用,应用层无需关注
---
## 🔧 管理工具连接方式
### 使用 kubectl port-forward(推荐)
#### 方式一:连接主节点
```bash
# 转发主节点服务到本地
kubectl port-forward -n juwan svc/user-redis-master 6379:6379
# 或直接转发到 Pod
kubectl port-forward -n juwan pod/user-redis-0 6379:6379
```
然后在管理工具中配置:
- **Host**: localhost
- **Port**: 6379
- **Password**: (见下方获取方法)
#### 方式二:使用 LoadBalancer(生产不推荐)
```yaml
# 临时暴露服务(仅用于调试)
apiVersion: v1
kind: Service
metadata:
name: redis-external
namespace: juwan
spec:
type: LoadBalancer
selector:
app: user-redis
ports:
- port: 6379
targetPort: 6379
```
---
### 获取 Redis 密码
```bash
# 方式一:直接输出
kubectl get secret user-redis -n juwan -o jsonpath='{.data.password}' | base64 -d
# 方式二:设置为环境变量
export REDIS_PASSWORD=$(kubectl get secret user-redis -n juwan -o jsonpath='{.data.password}' | base64 -d)
echo $REDIS_PASSWORD
# 方式三:保存到文件
kubectl get secret user-redis -n juwan -o jsonpath='{.data.password}' | base64 -d > redis-password.txt
```
---
### 常用管理工具配置
#### Redis Desktop Manager (RedisInsight)
```
Connection Name: juwan-user-redis
Host: localhost (使用 port-forward)
Port: 6379
Username: (留空)
Password: (从 Secret 获取)
```
#### redis-cli
```bash
# 在集群内访问
kubectl exec -it user-redis-0 -n juwan -- redis-cli -a <password>
# 从本地访问(需要 port-forward
redis-cli -h localhost -p 6379 -a <password>
# 常用命令
INFO replication # 查看复制状态
INFO stats # 查看统计信息
CLUSTER INFO # 查看集群信息
KEYS * # 查看所有 key(生产谨慎使用)
```
---
## 💻 应用服务连接方式
### 方案一:Sentinel 模式(生产强烈推荐)⭐⭐⭐
**优点**
- ✅ 自动故障转移
- ✅ 高可用
- ✅ 无需手动切换
- ✅ 客户端自动重连
- ✅ 支持读写分离
#### Go-Zero 配置
**配置文件** `app/users/rpc/etc/pb.yaml`
```yaml
Name: pb.rpc
ListenOn: 0.0.0.0:9001
# Redis Sentinel 配置
Redis:
Type: sentinel
MasterName: mymaster
SentinelAddrs:
- user-redis-sentinel-sentinel.juwan.svc.cluster.local:26379
Pass: ${REDIS_PASSWORD} # 从环境变量读取
Etcd:
Hosts:
- etcd-service.juwan.svc.cluster.local:2379
Key: pb.rpc
```
**Config 结构** `app/users/rpc/internal/config/config.go`
```go
package config
import (
"github.com/zeromicro/go-zero/core/stores/redis"
"github.com/zeromicro/go-zero/zrpc"
)
type Config struct {
zrpc.RpcServerConf
Redis redis.RedisConf
}
```
**初始化 Redis** `app/users/rpc/internal/svc/serviceContext.go`
```go
package svc
import (
"github.com/zeromicro/go-zero/core/stores/redis"
"juwan-backend/app/users/rpc/internal/config"
)
type ServiceContext struct {
Config config.Config
Redis *redis.Redis
}
func NewServiceContext(c config.Config) *ServiceContext {
return &ServiceContext{
Config: c,
Redis: redis.MustNewRedis(c.Redis),
}
}
```
**使用示例** `app/users/rpc/internal/logic/getUsersByIdLogic.go`
```go
func (l *GetUsersByIdLogic) GetUsersById(in *pb.GetUsersByIdReq) (*pb.GetUsersByIdResp, error) {
// 尝试从缓存获取
cacheKey := fmt.Sprintf("user:%d", in.Id)
cached, err := l.svcCtx.Redis.Get(cacheKey)
if err == nil && cached != "" {
// 缓存命中
var user pb.User
json.Unmarshal([]byte(cached), &user)
return &pb.GetUsersByIdResp{User: &user}, nil
}
// 从数据库查询
user := l.fetchUserFromDB(in.Id)
// 写入缓存
userJSON, _ := json.Marshal(user)
l.svcCtx.Redis.Setex(cacheKey, string(userJSON), 3600) // 1小时过期
return &pb.GetUsersByIdResp{User: user}, nil
}
```
#### Go (原生 go-redis)
```go
package main
import (
"context"
"github.com/redis/go-redis/v9"
"time"
)
func NewRedisClient() *redis.Client {
rdb := redis.NewFailoverClient(&redis.FailoverOptions{
MasterName: "mymaster",
SentinelAddrs: []string{
"user-redis-sentinel-sentinel.juwan.svc.cluster.local:26379",
},
Password: os.Getenv("REDIS_PASSWORD"),
DB: 0,
// 连接池配置
PoolSize: 10,
MinIdleConns: 5,
// 超时配置
DialTimeout: 5 * time.Second,
ReadTimeout: 3 * time.Second,
WriteTimeout: 3 * time.Second,
// 重试配置
MaxRetries: 3,
MinRetryBackoff: 8 * time.Millisecond,
MaxRetryBackoff: 512 * time.Millisecond,
})
// 测试连接
ctx := context.Background()
if err := rdb.Ping(ctx).Err(); err != nil {
panic(err)
}
return rdb
}
```
#### Python (redis-py)
```python
from redis.sentinel import Sentinel
import os
# 初始化 Sentinel
sentinel = Sentinel([
('user-redis-sentinel-sentinel.juwan.svc.cluster.local', 26379)
], socket_timeout=5.0)
# 获取主节点连接(用于写操作)
master = sentinel.master_for(
'mymaster',
password=os.getenv('REDIS_PASSWORD'),
socket_timeout=3.0,
socket_connect_timeout=5.0,
socket_keepalive=True,
socket_keepalive_options={},
connection_pool_kwargs={
'max_connections': 50
}
)
# 获取从节点连接(用于读操作)
slave = sentinel.slave_for(
'mymaster',
password=os.getenv('REDIS_PASSWORD'),
socket_timeout=3.0
)
# 使用
master.set('key', 'value')
value = slave.get('key')
```
#### Java (Spring Data Redis)
```yaml
# application.yml
spring:
redis:
timeout: 3000ms
password: ${REDIS_PASSWORD}
sentinel:
master: mymaster
nodes:
- user-redis-sentinel-sentinel.juwan.svc.cluster.local:26379
lettuce:
pool:
max-active: 10
max-idle: 5
min-idle: 2
max-wait: 3000ms
```
```java
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(
RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
return template;
}
}
```
---
### 方案二:主从分离模式 ⭐
**优点**
- ✅ 读写性能优化
- ✅ 配置清晰
- ⚠️ 需要手动处理故障
**Go-Zero 配置**
```yaml
# app/users/rpc/etc/pb.yaml
Redis:
- Host: user-redis-master.juwan.svc.cluster.local:6379
Type: node
Pass: ${REDIS_PASSWORD}
- Host: user-redis-replica.juwan.svc.cluster.local:6379
Type: node
Pass: ${REDIS_PASSWORD}
```
**代码示例**
```go
type ServiceContext struct {
Config config.Config
RedisMaster *redis.Redis // 写操作
RedisReplica *redis.Redis // 读操作
}
func NewServiceContext(c config.Config) *ServiceContext {
return &ServiceContext{
Config: c,
RedisMaster: redis.MustNewRedis(c.Redis[0]), // master
RedisReplica: redis.MustNewRedis(c.Redis[1]), // replica
}
}
// 写操作
l.svcCtx.RedisMaster.Set("key", "value")
// 读操作
val, _ := l.svcCtx.RedisReplica.Get("key")
```
---
### 方案三:简单模式(仅测试环境)
```yaml
Redis:
Host: user-redis-master.juwan.svc.cluster.local:6379
Type: node
Pass: ${REDIS_PASSWORD}
```
---
### Kubernetes Deployment 配置
```yaml
# deploy/k8s/service/user/user-rpc.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-rpc
namespace: juwan
spec:
template:
spec:
containers:
- name: user-rpc
image: user-rpc:v1
env:
# 数据库连接
- name: DB_URI
valueFrom:
secretKeyRef:
name: user-db-app
key: uri
# Redis 密码
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: user-redis
key: password
# 健康检查
readinessProbe:
tcpSocket:
port: 9001
initialDelaySeconds: 10
periodSeconds: 10
livenessProbe:
tcpSocket:
port: 9001
initialDelaySeconds: 15
periodSeconds: 20
```
---
## 📊 连接方式对比
| 连接方式 | 优点 | 缺点 | 故障转移 | 读写分离 | 复杂度 | 推荐度 |
|---------|------|------|---------|---------|--------|--------|
| **Sentinel 模式** | 自动高可用,客户端自动切换 | 配置稍复杂 | ✅ 自动 | ✅ 支持 | 中 | ⭐⭐⭐⭐⭐ |
| **主从分离** | 性能优化,逻辑清晰 | 需手动处理故障 | ❌ 手动 | ✅ 支持 | 中 | ⭐⭐⭐ |
| **仅连 Master** | 配置简单,强一致性 | 单点故障,读性能差 | ❌ 手动 | ❌ 不支持 | 低 | ⭐⭐ |
| **仅连 Replica** | 读性能好 | 只读,不能写入 | ❌ 手动 | ✅ 仅读 | 低 | ⭐ |
| **连 user-redis** | 极简单 | 性能差,不可靠 | ❌ 无 | ❌ 不支持 | 低 | ❌ |
---
## 🎯 最佳实践建议
### 生产环境(强烈推荐)
```yaml
# 使用 Sentinel 模式
Redis:
Type: sentinel
MasterName: mymaster
SentinelAddrs:
- user-redis-sentinel-sentinel.juwan.svc.cluster.local:26379
Pass: ${REDIS_PASSWORD}
# 连接池配置
PoolSize: 10
MinIdleConns: 5
# 超时配置
DialTimeout: 5s
ReadTimeout: 3s
WriteTimeout: 3s
# 重试配置
MaxRetries: 3
```
**理由**
- ✅ 自动故障转移,RTO < 30秒
- ✅ 客户端无感知切换
- ✅ 无需人工介入
- ✅ 久经考验的成熟方案
---
### 开发/测试环境
```yaml
# 简化配置,直连主节点
Redis:
Host: user-redis-master.juwan.svc.cluster.local:6379
Type: node
Pass: ${REDIS_PASSWORD}
```
或使用 port-forward
```bash
kubectl port-forward -n juwan svc/user-redis-master 6379:6379
```
---
### 性能优化建议
#### 1. 连接池配置
```go
PoolSize: runtime.NumCPU() * 2, // CPU 数量的 2 倍
MinIdleConns: runtime.NumCPU(), // CPU 数量
MaxConnAge: 30 * time.Minute, // 连接最大存活时间
```
#### 2. 超时配置
```go
DialTimeout: 5 * time.Second, // 连接超时
ReadTimeout: 3 * time.Second, // 读超时
WriteTimeout: 3 * time.Second, // 写超时
PoolTimeout: 4 * time.Second, // 获取连接超时
```
#### 3. 命令优化
```go
// ❌ 避免:循环中多次调用
for i := 0; i < 1000; i++ {
rdb.Set(ctx, fmt.Sprintf("key:%d", i), i)
}
// ✅ 推荐:使用 Pipeline
pipe := rdb.Pipeline()
for i := 0; i < 1000; i++ {
pipe.Set(ctx, fmt.Sprintf("key:%d", i), i, 0)
}
pipe.Exec(ctx)
```
#### 4. 缓存策略
```go
// Cache-Aside Pattern
func GetUser(id int64) (*User, error) {
// 1. 先查缓存
cacheKey := fmt.Sprintf("user:%d", id)
cached, err := rdb.Get(ctx, cacheKey).Result()
if err == nil {
var user User
json.Unmarshal([]byte(cached), &user)
return &user, nil
}
// 2. 缓存未命中,查数据库
user := queryFromDB(id)
// 3. 写入缓存
userJSON, _ := json.Marshal(user)
rdb.Set(ctx, cacheKey, userJSON, 1*time.Hour)
return user, nil
}
```
---
### 监控配置
#### Prometheus 指标采集
```yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: redis-exporter
namespace: juwan
spec:
selector:
matchLabels:
app: user-redis
endpoints:
- port: redis-exporter # 端口 9121
interval: 30s
path: /metrics
```
#### 关键指标监控
```yaml
# 告警规则示例
groups:
- name: redis
rules:
# Redis 实例宕机
- alert: RedisDown
expr: redis_up == 0
for: 1m
annotations:
summary: "Redis instance down"
# 内存使用率过高
- alert: RedisMemoryHigh
expr: redis_memory_used_bytes / redis_memory_max_bytes > 0.9
for: 5m
annotations:
summary: "Redis memory usage > 90%"
# 连接数过高
- alert: RedisConnectionsHigh
expr: redis_connected_clients > 1000
for: 5m
annotations:
summary: "Redis connections > 1000"
```
---
### 安全建议
#### 1. 密码管理
```bash
# 定期轮换密码
kubectl create secret generic user-redis \
--from-literal=password=$(openssl rand -base64 32) \
--dry-run=client -o yaml | kubectl apply -f -
# 重启 Redis Pods 使新密码生效
kubectl rollout restart statefulset/user-redis -n juwan
```
#### 2. 网络策略
```yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: redis-access
namespace: juwan
spec:
podSelector:
matchLabels:
app: user-redis
policyTypes:
- Ingress
ingress:
# 只允许同命名空间的 user-rpc 访问
- from:
- podSelector:
matchLabels:
app: user-rpc
ports:
- protocol: TCP
port: 6379
```
#### 3. TLS 加密(可选)
```yaml
# Redis TLS 配置
apiVersion: redis.redis.opstreelabs.in/v1beta2
kind: RedisReplication
metadata:
name: user-redis
spec:
TLS:
enabled: true
secret:
secretName: redis-tls-cert
```
---
## 🔍 故障排查
### 1. 连接失败
**症状**
```
Error: dial tcp 10.97.120.76:6379: i/o timeout
```
**排查步骤**
```bash
# 1. 检查 Service 是否存在
kubectl get svc user-redis-master -n juwan
# 2. 检查 Endpoints
kubectl get endpoints user-redis-master -n juwan
# 3. 检查 Pod 状态
kubectl get pods -l app=user-redis -n juwan
# 4. 测试网络连通性
kubectl run -it --rm netshoot --image=nicolaka/netshoot --restart=Never -n juwan -- \
nc -zv user-redis-master 6379
# 5. 查看 Pod 日志
kubectl logs user-redis-0 -n juwan -c redis
```
---
### 2. 认证失败
**症状**
```
Error: NOAUTH Authentication required
```
**解决方法**
```bash
# 1. 确认 Secret 存在
kubectl get secret user-redis -n juwan
# 2. 验证密码
PASSWORD=$(kubectl get secret user-redis -n juwan -o jsonpath='{.data.password}' | base64 -d)
echo $PASSWORD
# 3. 测试连接
kubectl exec -it user-redis-0 -n juwan -- redis-cli -a $PASSWORD PING
```
---
### 3. 主从复制异常
**症状**
```
Warning: Redis replica lag is high
```
**排查**
```bash
# 在主节点执行
kubectl exec -it user-redis-0 -n juwan -- redis-cli -a <password> INFO replication
# 查看输出
# role:master
# connected_slaves:2
# slave0:ip=10.244.1.10,port=6379,state=online,offset=1234,lag=0
# slave1:ip=10.244.2.15,port=6379,state=online,offset=1234,lag=0
```
**如果 lag 过大**
```bash
# 检查网络延迟
kubectl exec -it user-redis-0 -n juwan -- ping user-redis-1
# 检查 Redis 性能
kubectl exec -it user-redis-0 -n juwan -- redis-cli -a <password> INFO stats
```
---
### 4. Sentinel 无法发现主节点
**症状**
```
Error: sentinel: no master found
```
**排查**
```bash
# 1. 检查 Sentinel 状态
kubectl exec -it user-redis-sentinel-sentinel-0 -n juwan -- \
redis-cli -p 26379 SENTINEL masters
# 2. 检查主节点地址
kubectl exec -it user-redis-sentinel-sentinel-0 -n juwan -- \
redis-cli -p 26379 SENTINEL get-master-addr-by-name mymaster
# 3. 查看 Sentinel 日志
kubectl logs user-redis-sentinel-sentinel-0 -n juwan
# 4. 手动触发故障转移(慎用)
kubectl exec -it user-redis-sentinel-sentinel-0 -n juwan -- \
redis-cli -p 26379 SENTINEL failover mymaster
```
---
### 5. 性能问题
**慢查询分析**
```bash
# 查看慢查询
kubectl exec -it user-redis-0 -n juwan -- \
redis-cli -a <password> SLOWLOG GET 10
# 设置慢查询阈值(10ms
kubectl exec -it user-redis-0 -n juwan -- \
redis-cli -a <password> CONFIG SET slowlog-log-slower-than 10000
```
**命令统计**
```bash
# 查看命令统计
kubectl exec -it user-redis-0 -n juwan -- \
redis-cli -a <password> INFO commandstats
```
**内存分析**
```bash
# 查看内存使用
kubectl exec -it user-redis-0 -n juwan -- \
redis-cli -a <password> INFO memory
# 查看大 key
kubectl exec -it user-redis-0 -n juwan -- \
redis-cli -a <password> --bigkeys
```
---
## 📚 参考资源
### 官方文档
- [Redis Sentinel Documentation](https://redis.io/docs/management/sentinel/)
- [go-redis Documentation](https://redis.uptrace.dev/)
- [OpsTree Redis Operator](https://ot-redis-operator.netlify.app/)
### 客户端库
- Go: [github.com/redis/go-redis/v9](https://github.com/redis/go-redis)
- Python: [redis-py](https://github.com/redis/redis-py)
- Java: [Spring Data Redis](https://spring.io/projects/spring-data-redis)
- Node.js: [ioredis](https://github.com/luin/ioredis)
### 监控工具
- [RedisInsight](https://redis.com/redis-enterprise/redis-insight/)
- [Redis Exporter](https://github.com/oliver006/redis_exporter)
- Grafana Dashboard: [Redis Dashboard 11835](https://grafana.com/grafana/dashboards/11835)
---
## 📝 更新日志
| 日期 | 版本 | 变更内容 |
|------|------|---------|
| 2026-02-22 | 1.0 | 初始版本,包含完整的 Service 介绍和连接指南 |
---
**文档维护者**: DevOps Team
**最后更新**: 2026年2月22日
**下一次审查**: 2026年3月22日