# 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日
