Files
Qiniu/technical/xinfra-preview/cachecloud-overview.md
T

14 KiB
Raw Blame History

tags, create time
tags create time
cachecloud
redis
infra
self-hosted
2026-07-04 12:00

CacheCloud Redis 管理台

概述

CacheCloud(搜狐开源)是一个 Redis 私有云平台,支持 Standalone、Sentinel、Cluster 三种架构的一站式高效管理。xinfra 中所有需要 Redis 服务的场景都通过 CacheCloud 进行统一的实例申请和管理——开发同学不再需要手动安装部署 Redis,只需在平台上提交工单即可获取可用实例。

核心目标:降低大规模 Redis 运维成本,提升资源管控能力和利用率。平台提供快速搭建/迁移、运维管理、弹性伸缩、统计监控、客户端整合接入等功能。


系统架构

整体拓扑

graph TB
    subgraph "用户层"
        Dev[开发同学 / 运维人员]
    end

    subgraph "接入层 (Nginx 双机房)"
        NG1[Nginx 机房 A]
        NG2[Nginx 机房 B]
        VIP[Virtual IP → 双向漂移]
        VIP --> NG1
        VIP --> NG2
    end

    subgraph "应用层 (Spring Boot)"
        CC[CacheCloud Web Server]
        DB[(MySQL 元数据)]
        AGT_Mgr[Agent 管理器]
        ALERT[报警组件<br/>邮件 / 微信 / HTTP]
        CUSTOM[自定义扩展模块]
    end

    subgraph "执行层 (Agent 代理)"
        AGT1[Agent 宿主机 A<br/>Redis Standalone / Sentinel]
        AGT2[Agent 宿主机 B<br/>Redis Cluster Shard 1]
        AGT3[Agent 宿主机 C<br/>Redis Cluster Shard 2]
    end

    Dev -->|cc.company.com| VIP
    VIP --> NG1 & NG2
    NG1 & NG2 --> CC
    CC <--> DB
    CC --> AGT_Mgr
    CC --> ALERT
    CC --> CUSTOM
    AGT_Mgr -->|SSH + 心跳| AGT1 & AGT2 & AGT3

关键设计决策:CacheCloud 采用 Agent 模式而非直接 SSH 连接 Redis 实例。每个宿主机部署一个 Agent 进程,负责该机器上所有 Redis 实例的生命周期管理(启停、升级、备份恢复)。这样做的好处是 Agent 可复用 SSH 连接、缓存本地状态,大幅减少管理平台到 Redis 主机的网络开销。

核心组件

组件 职责
Web UI / REST API 自助申请实例、配置修改、工单审批、监控大屏
Agent 代理 部署在每个宿主机上,负责 Redis 进程生命周期管理、状态上报、远程命令执行
元数据库 (MySQL) 存储实例拓扑、配置模板、账号权限、工单流转记录
报警模块 内置邮件和微信报警,同时暴露 HTTP 接口供任意语言集成
扩展模块 登录组件 (LoginComponent)、报警组件 (EmailComponent/WeChatComponent) 均可自行实现

实例类型与选型指南

三种架构对比

维度 Standalone Sentinel (Master-Slave) Cluster
高可用 ❌ 单机,无 Failover ✅ 主从 + Sentinel 自动故障转移 ✅ 多分片,自动槽迁移
横向扩展 ❌ 受单机容量限制 ❌ 受单机容量限制 ✅ 新增节点即扩容
复杂度 简单 中等 较高
推荐场景 测试环境、低频读写缓存 生产环境常规业务、内存需求 ≤ 6GB 大数据量、高并发、内存需求 > 6GB

建议:并不是 Cluster 越好。如果当前或未来所需内存不超过 6GB 且要求高可用,选择 Sentinel 就足够了。

选型决策树

flowchart TD
    Start{是否需要高可用?}
    Start -->|否: 测试/灰度| Standalone[Standalone]
    Start -->|是| NeedScale{是否需要横向扩展?}
    NeedScale -->|否≤6GB| Sentinel[Sentinel 主从]
    NeedScale -->|是>6GB| Cluster[Redis Cluster]

客户端接入方式

CacheCloud 提供了多种客户端 SDK 及 REST API,覆盖 Java、Python 等主流语言。

REST API(最通用)

通过简单 HTTP 请求即可获取实例连接信息,适用于任何语言:

GET http://{domain}/cache/client/redis/{appType}/{appId}.json?clientVersion={version}

参数说明:

参数 含义 枚举值
appType 实例类型 cluster / sentinel / standalone
appId 应用 ID 平台分配的数字 ID

响应示例:

{
  "message": "client is up to date, Cheers!",
  "shardNum": 10,
  "appId": 10192,
  "status": 1,
  "shardInfo": "10.10.xx.xx:6390,10.10.xx.xx:6382 10.10.xx.xx:6387,10.10.xx.xx:6379 ..."
}

shardInfo 字段以空格分隔每个分片,逗号分隔同一个分片的主从地址。解析后即可直连。

Java — cachecloud-client-redis(Jedis 封装)

@Configuration
public class RedisConfiguration {

    @Bean(destroyMethod = "close")
    public PipelineCluster pipelineCluster(@Value("${cachecloud.demo.appId}") long appId) {
        return ClientBuilder.redisCluster(appId).build();
    }

    @Bean(destroyMethod = "destroy")
    public JedisSentinelPool jedisSentinelPool(@Value("${cachecloud.demo.appId}") long appId) {
        return ClientBuilder.redisSentinel(appId).build();
    }

    @Bean(destroyMethod = "destroy")
    public JedisPool jedisPool(@Value("${cachecloud.demo.appId}") long appId) {
        return ClientBuilder.redisStandalone(appId).build();
    }
}

使用方式:

@Autowired private PipelineCluster pipelineCluster;

public String get(String key) {
    return pipelineCluster.get(key);
}

所有 ...Pool.getResource() 使用后必须调用 jedis.close() —— 它并非真正关闭连接,而是将连接归还给连接池(内部判断连接是否损坏后决定 returnResource 还是 returnBrokenResource)。

Java — cachecloud-client-lettuce(Lettuce 封装)

适合需要异步/响应式场景的应用:

@Bean(destroyMethod = "shutdown")
public RedisClusterClient redisClusterClient(long appId, String password) {
    return LettuceClientBuilder.redisCluster(appId, password).build();
}

@Bean(destroyMethod = "close")
public StatefulRedisClusterConnection<String, String> clusterConnection(RedisClusterClient client) {
    StatefulRedisClusterConnection<String, String> conn = client.connect();
    conn.setReadFrom(ReadFrom.REPLICA_PREFERRED); // 读操作优先走从节点
    return conn;
}

Python 接入(REST API 动态拉取连接信息)

import requests
from rediscluster import RedisCluster

app_id = 10192
url = f'http://cc.company.com/cache/client/redis/cluster/{app_id}.json'
resp = requests.get(url).json()

startup_nodes = [
    dict(zip(['host', 'port'], addr.split(':')))
    for shard in resp['shardInfo'].split(' ')
    for addr in shard.split(',')
]
rc = RedisCluster(startup_nodes=startup_nodes, password='your-pass')

跨机房部署(Cross-Room)

对于容灾要求高的业务,CacheCloud 支持跨机房双活:同一业务在两个机房分别部署应用实例,客户端 SDK 自动做双写双读和机房切换。原理是两个 PipelineCluster 实例被包装进一个 RedisCrossRoomClient。


系统功能全景

用户端功能

功能 说明
应用管理 查看统计信息、实例列表、应用拓扑、连接信息
监控面板 命令曲线、延迟监控、日报统计
命令执行 在线执行 Redis 命令用于排查
键值分析 分析 bigkey、hotkey 分布

运维端功能

功能分类 具体能力
数据统计 全局统计、client 统计、server 统计
工单审批 实例申请、配置修改、数据清理等操作需管理员审批
应用运维 应用维度的启停、配置下发、日志查看
实例运维 实例维度的启停、配置查询、数据清理
数据迁移 跨实例数据迁移工具
诊断工具 慢查询分析、连接数诊断等
模板管理 按规格预设 Redis 配置模板(maxmemory、持久化策略等)
任务流 编排运维操作流程(如批量升级)

报警配置

CacheCloud 内置的报警覆盖了 Redis 机器级别和实例级别的重要指标,支持的报警渠道:

  • 邮件报警 — 默认实现,也可替换为 HTTP 回调
  • 微信报警 — 企业微信/钉钉 webhook 风格

报警可通过 HTTP 接口自定义,格式如下:

POST www.xxx.com/emailAlert?title=xx&content=xx&receiver=x&cc=x
POST www.xxx.com/weChatAlert?title=xx&message=xx&weChatList=xx

基础运维实践

maxmemory-policy 策略选择

策略 行为 适用场景
volatile-lru 删除有过期时间的 key,LRU 淘汰 默认策略,有 TTL 的缓存
allkeys-lru 对所有 key 做 LRU 淘汰 纯缓存场景,不设 TTL
volatile-ttl 删除即将过期的 key 希望按过期时间优先淘汰
noeviction 不淘汰,写操作返回错误 需要绝对保证数据完整性

注意:修改的配置会对应用的所有节点生效,因为所有节点的配置是统一的。

Jedis 连接池调优参考

GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
poolConfig.setMaxTotal(DEFAULT_MAX_TOTAL * 5);   // 根据实际 QPS 调整
poolConfig.setMaxIdle(DEFAULT_MAX_IDLE * 3);
poolConfig.setMinIdle(DEFAULT_MIN_IDLE * 2);
poolConfig.setMaxWaitMillis(3000);                 // 连接耗尽时最多等待 3s
poolConfig.setJmxEnabled(true);                    // 开启 JMX 便于观察
poolConfig.setTestWhileIdle(true);                // 空闲时定期检查连接有效性
poolConfig.setTimeBetweenEvictionRunsMillis(60000); // 每分钟检查一次

关键字段解读:

配置项 默认值 调优建议
maxTotal 8 根据峰值连接数估算,通常 × 3~5
testOnBorrow false 不建议设为 true,会显著增加延迟
testOnReturn false 一般保持 false,由 testWhileIdle 兜底
whenExhaustedAction 1 (阻塞) 配合 maxWaitMillis 使用,避免无限等待

常见陷阱与最佳实践

1. Bigkey 的寻找与优化

什么是 bigkey:value 所占内存空间较大的 key。字符串类型超过 100KB 即视为 bigkey;非字符串类型(Hash/List/Set/ZSet)则以元素数量过多为准。

危害:

  • 内存不均匀:Cluster 中造成部分节点内存暴增
  • 超时阻塞:Redis 单线程特性下,大 key 操作耗时 > 客户端超时
  • 网络拥塞:单次大流量冲击网卡,影响同机其他实例
  • 过期删除阻塞:未启用 lazyfree 时阻塞主线程
  • 碎片整理冲突:Redis 4.0+ activeDefrag 对超大 key 可能导致周期性延迟

发现手段:

方法 命令 特点
redis-cli redis-cli --bigkeys 全量扫描,建议在从节点执行
DEBUG OBJECT DEBUG OBJECT key 获知序列化长度 serializedlength
MEMORY USAGE MEMORY USAGE key 仅 Redis 4.0+,返回精确内存占用
监控输出缓冲区 info clients 关注 client_biggest_input_buf / client_recent_max_output_buffer 间接判断是否存在大 key 读取

优雅删除方案:

  • String:直接使用 DEL,通常不会阻塞
  • Hash/List/Set/ZSet:使用 HSCAN/SSCAN/ZSCAN 分批获取元素 + HDEL/SREM/ZREM 逐个删除,或使用 Redis 4.0+ 的 UNLINK(异步删除)
def del_big_hash(r, key):
    cursor = 0
    while True:
        cursor, members = r.hscan(key, cursor, count=100)
        if not members:
            break
        r.hdel(key, *members)  # pipeline 批量更高效
        if cursor == 0:
            break

2. Hotkey 的处理方向

当某个 key 的访问量远超平均水平时:

  • 本地缓存:在应用侧加一层 Guava/Caffeine 缓存
  • key 拆分:将一个大 key 拆成多个子 key(如 user:1001:friends → user:1001:friends:1, user:1001:friends:2)
  • 读写分离:读操作通过 Sentinel 路由到从节点

3. 实例规格匹配

不要盲目选大规格。建议先通过 Prometheus/Grafana 观察历史 QPS、内存使用和连接数,再确定实例规格。过度配置会在资源看板上体现为浪费。

4. 临时 vs 长期实例

  • 临时实例(测试/灰度用)应设置自动回收策略——超出保留期后系统自动销毁
  • 长期实例则需要完善监控、定期巡检配置变更

5. 机房就近原则

Redis 对网络延迟非常敏感。跨机房访问比同机房慢数倍,因此应用申请时应填写服务所在机房,确保实例分配到最近的机器。


Redis 版本演进速览

CacheCloud 管理的 Redis 实例可能运行在不同版本,了解各版本的关键特性有助于理解平台行为差异:

版本 核心新特性 CacheCloud 相关
3.x 原生 Cluster 最早支持的 Cluster 形态
4.0 Lazyfree 异步删除、AOF/RDB 混合持久化、内存碎片整理 支持 UNLINK 删除 bigkey
5.0 Stream 数据类型、RESP3 协议、Dynamic HZ 客户端兼容性更好
6.0 多线程 IO、ACL、SSL 加密、协助客户端缓存 多线程 IO 提升非 Pipeline 场景 2 倍性能

启发问题:为什么 Redis 6.0 的多线程只处理网络 IO 而不涉及命令执行?这背后有什么权衡?


与 xinfra 的对接方向

进阶目标中提到要「基于 CacheCloud API 实现页面直接创建 Redis Cluster」,这意味着:

  1. 阅读 Open API 文档:梳理可用的创建/配置/查询接口
  2. 封装创建流程:选择规格 → 调用 API → 等待就绪 → 返回连接信息
  3. 集成到 xinfra 统一服务管理页面:让开发者在 xinfra 内即可完成 Redis 实例的全生命周期操作
  4. 可选增强:对接 xinfra 的审批流、用量统计、成本分摊等模块

关联笔记