找回密码
立即注册
搜索
发回帖 发新帖

6303

积分

0

好友

801

主题
发表于 昨天 23:51 | 查看: 5| 回复: 0

一、前言

自建 Redis 系统是得物 DBA 团队自研的高性能分布式 KV 缓存系统,目前管理的 ECS 内存总容量超过数十 TB,承载数百个 Redis 缓存集群实例、数万个 Redis 数据节点,其中不乏内存规格超过 1T 的大容量集群。

这套系统采用 Proxy 架构,包含 ConfigServer、Redis-Proxy 等核心组件,并配套一套功能完善的自动化运维平台,覆盖实例自动化部署、资源管理、诊断与分析等场景。

本文将从系统架构与核心组件、支持的重要特性、自动化运维平台的关键能力等多方面,介绍自建 Redis 系统的设计与实践。

二、自建 Redis 架构及核心组件

自建 Redis 分布式 KV 缓存系统由 ConfigServer、Redis-Proxy、Redis-Server 三类核心组件构成,整体架构如下图所示:

自建Redis分布式缓存系统架构拓扑图

下面逐一介绍各核心组件支持的重要功能与特性。

ConfigServer

ConfigServer 是自建 Redis 系统中的关键组件之一,跨多可用区多节点部署,采用 Raft 协议实现 ConfigServer 组件高可用,主要负责三方面职责:

  • 负责 Proxy 添加与删除、Group 创建与删除、Redis-Server 实例添加与删除、手动主从切换、水平扩容与数据迁移等操作。
  • 集群拓扑发生变化时,主动向 Redis-Proxy 更新集群拓扑。
  • 负责 Redis-Server 实例的故障检测与自动故障转移(主节点故障后自动主从切换)。

ConfigServer 的系统结构如下:

ConfigServer系统结构图:包含Redis-Server HA与Console等模块

每个自建 Redis 集群会对应部署一组独立的 ConfigServer 组件,每组 ConfigServer 至少三节点部署,分布在三个不同的可用区,保障系统高可用:

  • ConfigServer 多节点多可用区部署,首先保证了组件自身的高可用。
  • 同时,也保障了 Redis-Server 的高可用。任意一个可用区故障,剩余 ConfigServer 依然能高效完成宕机判定、选主与 Failover。
  • 相对于开源 Redis 原生 Cluster 模式,这种设计不会因为多数 Redis-Server 主节点故障而导致无法完成故障判定与 Failover。

故障检测与转移

ConfigServer 负责 Redis-Server 节点的故障检测与自动故障转移。它会定期对每一个 Group 的 Master 节点进行探活,一旦发现某个 Group 的 Master 节点不可用,就执行 Failover 流程:从该 Group 内选出一个可用的 Slave 节点提升为新的 Master,保证该 Group 继续对外提供服务。

实现思路参考了开源 Redis Sentinel,不过 ConfigServer 是 Golang 实现,开源 Redis Sentinel 使用 C 语言实现,部分细节上存在差异。

多协程: 开源 Redis Sentinel 在单线程中定时检测所有 Redis-Server 节点;而得益于 Golang 的协程能力,ConfigServer 为实例的每个 Group 单独开启一个协程,在协程中定时检测该 Group 对应的 Redis-Server 状态。

自定义通讯协议: 开源 Redis Sentinel 中,Sentinel 之间通过 Redis-Server 节点交换元数据来发现负责同一节点的其他 Sentinel,以及交换观测状态;而 ConfigServer 节点之间直接采用自定义 TCP 协议通讯,信息交换更高效,故障切换时间也更短。

故障检测流程:

  • 每个 ConfigServer 定期给实例的所有 Redis-Server 节点发送 Ping 和 Info 命令,用于检测节点可用性和发现新从节点。
  • 当 ConfigServer 向 Redis-Server 节点发送命令超时时,将节点标记为主观下线,并传播该状态。
  • ConfigServer Leader 节点发现某节点处于主观下线后,会主动查询其他 ConfigServer 节点的判定结果。如果多数 ConfigServer 节点都将该 Redis-Server 节点标记为主观下线,Leader 节点就将其标记为客观下线,并发起故障转移。

故障转移流程:

  • 从故障 Redis 主节点的所有从节点中,按照以下策略选择最优从节点:
    • 过滤不健康的从节点,如处于主观下线或客观下线状态的节点。
    • 选择 Slave-Priority 最高的从节点。
    • 选择复制偏移量最大的从节点。
    • 选择 Runid 最小的从节点。
  • 将选出的从节点提升为新主节点,执行 slaveof no one。
  • 将其他从节点设置为新主节点的从节点。
  • 持续关注旧主节点状态,若旧主节点恢复,将其也更新为新主节点的从节点。

Redis-Proxy

Redis-Proxy 组件是自建 Redis 系统中的代理服务,负责接收客户端连接并转发客户端命令到后端相应的 Redis-Server 节点,使得后端 Redis-Server 集群部署架构对业务透明。Proxy 支持 Redis RESP 协议,业务访问 Proxy 就像访问一个单点 Redis 服务一样,可以把一个自建 Redis 集群当作容量无限大的单点实例来使用。

自建 Redis 为每个实例部署一组独立的 Proxy 节点。Proxy 是无状态服务,可以非常方便地进行水平扩容,提升业务访问自建 Redis 的 QPS。

在自建 Redis 中,每个集群可能包含多个 Group,每个 Group 对应一组主从 Redis-Server 节点,负责一部分 Key。整个集群划分为 1024 个槽(slot),每个 Group 负责其中一部分。用户写入的 Key 通过以下算法计算对应的 slot,然后存储到对应节点。

slot 计算公式:slot(key) = crc32(key) % 1024

Redis集群槽位分布示意图:Proxy通过crc32计算key归属

Proxy 接收用户命令后,提取访问的 Key,通过同样的算法计算 slot,获取负责该 slot 的 Redis-Server 实例连接,再将用户命令转发到对应实例执行,并读取返回结果发送给用户。

DBA 团队针对 Proxy 组件做了大量性能优化。相比市面上开源的支持 Redis RESP 协议的 Proxy 版本,临时对象内存分配减少了约 20 倍,极大减轻了 GC 压力以及 GC 消耗的 CPU;大量短链接场景下,QPS 提升约 10%。

除此之外,自建 Redis-Proxy 还支持同城双活、异步双写等特色功能。

同城双活

为了保证数据高可用和高可靠,每个 Redis 实例中的每个分组采用至少一主一从的部署方案,且主从节点分别部署在不同可用区。在默认访问模式下,业务读写都访问主节点,从节点仅作为热备节点。

为了提升业务在多可用区部署场景下的缓存访问性能、降低延迟,同时最大化利用从节点价值,自建 Redis-Proxy 支持同城双活。同城双活采用单写就近读方案,实现原理如下所示:

Redis同城双活容灾架构图:主备可用区就近读

动态配置需要通过以下方式之一实现:

  • 容器应用优先通过 ServiceName 实现同 AZ Proxy 节点优先访问(优先方案)。
  • 通过云厂商的 PrivateZone 实现智能 DNS 解析(容器和非容器应用均可)。

Redis-Server 部署规则:

  • 采用至少一主一从的部署方案,主从节点跨可用区部署,分别部署在与业务对应的可用区。

Redis-Proxy 部署规则:

  • Redis-Proxy 同样采用多可用区部署,与业务可用区相同。
  • 各可用区的 Proxy 将写请求自动路由到主节点,保持单点写入。
  • 读请求优先就近访问本可用区从节点;本可用区无可用从节点时,自动访问主节点或优先访问其他可用区从节点。

异步双写

针对业务从云 Redis 迁移到自建 Redis、以及大集群拆分等场景,对于数据可靠性要求较高的业务,Proxy 支持双写功能。

以从云 Redis 迁移到自建 Redis 为例,迁移期间 Proxy 同时写云 Redis 和自建 Redis,保证两边数据实时一致,从而可以随时回滚,实现平滑迁移。

Proxy 双写功能具备以下特点:

  • 采用异步双写实现,性能优异,双写操作对业务几乎无影响。
  • 支持转发、只读、双写等多种模式。业务接入自建 Redis 后,可以在线动态更改配置,平滑完成整个切换过程,无需频繁修改配置或重启。
  • 支持云 Redis 优先或自建 Redis 优先(以云 Redis 迁移为例),且可在线动态调整。
  • 提供数据比对工具,用于双写期间的数据一致性观察。数据对比支持多种策略,包括对比类型、对比长度或元素数量。

Redis-Server

Redis-Server 组件在开源 Redis 版本基础上,增加了槽 slot 同步迁移与异步迁移等相关功能;同时完整支持原生开源 Redis 的所有特性,比如 String、Hash、List、Set、ZSet 等常用数据结构,AOF 持久化、主从复制、Lua 脚本等。

Share-Nothing 架构: 自建 Redis 中,Redis-Server 以集群化方式部署。整个集群由多个 Group 组成,每个 Group 包含一主 N 从多个 Redis-Server 实例。Group 之间的 Redis-Server 节点相互没有通信,采用 Share-Nothing 架构。整个集群划分为 1024 个槽(slot),每个 Group 负责其中一部分。用户写入的 Key 通过上述算法计算 slot,然后存储到负责该 slot 的 Group 中的 Redis-Server 节点上。查询时同样通过算法路由到对应节点。

Async-Fork 特性

在 Redis 中,AOF 文件重写、RDB 备份文件生成以及主从全量同步过程,都需要调用系统调用 Fork 创建子进程来获取内存数据快照。Fork() 创建子进程时,内核会把父进程的「页表」复制一份给子进程。如果页表很大,在现有常见操作系统中,复制页表的过程耗时会非常长,在此期间业务访问 Redis 的读写延迟会大幅增加。

自建 Redis 通过优化并适配最新支持 Async-Fork 特性的操作系统,极大提升了 Fork 操作性能:

  • Fork 命令耗时大幅减小,且不随数据量增长而增长,基本稳定在 200 微秒左右。
  • TP100 抖动得到明显改善,TP100 值不随数据量增长而变大,基本维持在 1-2 毫秒。
  • 相比原生 Redis Fork 耗时减少 98%。日常运维中,添加从节点、主从切换、RDB 离线分析等常见运维操作对业务无感知,不会造成业务性能抖动。

fork与Async-fork耗时对比柱状图

压测时执行bgsave的tp100性能对比柱状图

注:以上图表使用双纵坐标。详细内容可参阅《VLDB 顶会论文 Async-fork 解读与 Redis 实践》。

数据迁移

为什么要做数据迁移?主要是为了水平扩容。自建 Redis 将每个集群实例划分为固定数量的槽 slot,每个 Group 负责一部分。水平扩容时,需要重新分配 slot 的分布,并将一部分 slot 从原有节点迁移到新节点,同时将这些 slot 对应的数据一并迁移过去。

迁移过程是:在源节点将 Key 对应的 Value 使用 Dump 命令进行序列化,发送到目标节点;目标节点使用 Restore 命令将 Key 和 Value 存储到本地 Redis;最后源节点删除该 Key。

自建 Redis 支持同步迁移与异步迁移两种方式。

Redis同步迁移时序图

Redis异步迁移时序图

同步迁移:在整个迁移过程中,源端 Migrate 命令处于阻塞状态,直到目标端成功加载数据并返回成功、源节点删除该 Key 后,Migrate 命令才向客户端响应成功。由于 Redis 数据操作是单线程模型,所有命令都在主线程中处理,因此同步迁移会极大地影响其他正常业务的访问。

异步迁移:Migrate 命令仅阻塞 Dump 序列化数据阶段,然后异步发送到目标节点并立即向客户端返回成功。目标节点接收数据后使用 Restore 命令保存,保存成功后给源节点发送 ACK,通知源节点删除已迁移的 Key。异步迁移减少了源端 Migrate 命令的阻塞时间,从而降低了 slot 迁移过程中对业务的影响。

三、自动化运维平台

自建 Redis 系统拥有功能完善的自动化运维平台,主要能力包括:缓存实例自动化部署、快速水平扩容与垂直扩容、多维度资源管理、诊断与分析等。

运维平台架构

自建 Redis 自动化运维平台包含 Redis 管控平台、Kv-Admin、Kv-Agent、Prometheus 等组件,部署架构如下:

Redis自动化运维平台架构图:管控平台与Kv-Agent交互

Redis 管控平台是自建 Redis 的综合运维管理平台,所有可视化操作都在该平台上完成,包括实例部署、扩容、数据迁移等日常运维操作。

Kv-Admin 是自动化运维平台的核心组件,负责处理所有前端请求,核心功能包括:

  • 实例部署时的任务调度、机器推荐、端口分配、SLB 推荐与绑定。
  • 实例列表展示、实例基本信息查询。
  • 数据离线分析与保存。
  • 资源池管理及生成资源报表。

Kv-Agent 部署在每个 ECS 上,负责实例部署、实例启停等操作;基于心跳元数据实现 Exporter 自动注册与解除。Kv-Agent 内置 Exporter 模块,负责 Redis-Server 节点的监控信息采集,规范化后通过端点暴露给 Prometheus。

APM / Prometheus:APM 监控平台或 Prometheus 负责从 Exporter 暴露的端点拉取监控数据。自建 Redis 的监控与告警均接入公司 APM 平台。

实例自动化部署

一个缓存实例的部署链路相当复杂,涉及机器选择、配置文件准备、节点安装与启动、槽位分配、主从关系设置、SLB 分配与绑定以及相关组件的部署等一系列动作。

自动化运维平台支持安装包版本管理。在部署页面选择合适的包版本、配置实例可用区与规格等基本信息后,一键操作即可完成 ConfigServer、Redis-Proxy、Redis-Server 等组件的部署,自动完成部署过程中涉及的机器推荐、配置文件准备、节点安装与启动等全部流程。

实例自动化部署流程:Kv-Admin与Kv-Agent交互

为了保证实例中各组件的高可用,自动化部署过程内置了必要的部署规则:

  • ConfigServer 组件部署在三个不同的可用区。
  • 避免同一个集群实例的多个 Redis-Server、Redis-Proxy 节点部署在相同 ECS 上;每个 ECS 上可部署的同一集群实例的 Server 或 Proxy 数量可配置。
  • 每个 ECS 最多分配总内存容量的 90%,预留数据增长空间。
  • 根据 ECS 可用内存,优先推荐剩余可用内存多的 ECS。
  • 根据 Group 数量,自动均衡分配每个 Group 负责的 slot 数量。
  • 根据 SLB 近三天的流量峰值,自动绑定最优 SLB。

实例扩容

当业务数据增长导致实例内存使用率超过阈值后,根据单节点分配的最大内存、实例 Group 数量等因素综合判断,运维可选择垂直扩容或水平扩容。

垂直扩容:动态修改单节点的 Maxmemory 参数,提高单节点容量。一般来说,单节点规格小于 4G 时优先考虑垂直扩容,操作简单快速,对业务无任何影响。

水平扩容:增加实例的 Group 数量,对应增加主从节点数量,然后重新进行 slot 分配与数据迁移。同初始部署一样,运维平台支持新增 Redis-Server 节点的自动化部署、主从关系设置,自动均衡分配每个 Group 负责的 slot 数量,并自动完成数据迁移,迁移进度可视化。

资源管理

自建 Redis 运维平台目前管理 ECS 超过数千台,支持批量添加、资源分配、资源锁定、资源推荐等资源管理功能,并提供资源利用率报表。

运维平台管理每台 ECS 的剩余可分配内存容量。Redis-Server 实例部署时,优先推荐剩余可分配内存多的 ECS;分配后同步更新可用内存容量。Redis-Proxy 和 ConfigServer 部署时,优先推荐已部署实例数量较少的 ECS。

诊断与分析

计算实例综合得分: 运维平台分析所有实例关键监控指标前一天的峰值,按照各项指标权重,每天自动计算所有实例的得分。通过得分可以快速了解各实例的使用健康度。参与计算的关键指标包括:Proxy CPU、Redis CPU、Redis 内存使用率、Proxy 占用内存、Proxy GC 次数、最大 RT、Redis 流入/流出流量等。

慢日志: 支持 Redis-Server 记录的慢日志和 Redis-Proxy 记录的慢日志查询。

RDB 离线分析: 运维平台支持生成 RDB 文件并自动进行数据离线分析。分析结果包含 Top100 Value 最大的 Key 和元素个数最多的 Key;每种类型 Key、不同 Key 前缀包含的 Key 数量等。

RDB离线分析仪表盘:mem usage与key数量分布

四、监控与告警

自建 Redis 系统接入 APM 监控平台,提供各种维度的监控指标和告警功能,既能在异常发生前及时预警,也能在问题出现后帮助快速定位。

监控

  • ECS: CPU、系统 Load、内存、网络流量、网络丢包、磁盘 IO 等。
  • Proxy: QPS、TP999/TP9999/TP100、连接数、CPU、内存、GC、Goroutine 数量等。
  • Server: CPU、内存、网络、连接数、QPS、Key 数量、命中率、访问 RT 等。

告警

自建 Redis 包含大量告警指标,例如:

  • ECS CPU 使用率、内存使用率、系统 Load(5 分钟平均值)、流量。
  • SLB 流量。
  • Server、Proxy、ConfigServer 节点宕机。
  • 主节点缺失从节点、主节点可用区不一致、主从角色切换。

五、稳定性治理

资源隔离

自建 Redis 所有组件都部署在 ECS 上。为了提高资源利用率、节约成本,大部分业务域的 Redis 集群采用混布方式。运维平台目前管理 ECS 超过数千台,接入业务涵盖营销、风控、算法、投放、社区、大数据等,每个业务的实例等级、QPS、流量各有差异。少数业务可能存在突发写入流量高、Proxy CPU 毛刺等现象,可能引起相同 ECS 上其他实例性能抖动。

按标签分类: 为方便资源隔离与分配管理,所有 ECS 资源按标签进行分类管理。针对特殊需求业务、大流量实例、通用资源池等划分不同资源标签。实例部署时选择合适的标签;频繁告警时调整到对应资源池隔离,避免相互影响。

Proxy CPU 限制: 为防止单个 Redis-Proxy 进程抢占过多 CPU 资源,Redis-Proxy 支持通过 Golang GOMAXPROCS 参数设置单个进程允许使用的最大 CPU 核数。

巡检

为了提前发现潜在风险,除了日常告警外,团队还建设了自动巡检工具和巡检信息页面,建立定期巡检机制。

实例综合得分排名: 运维平台每天自动计算所有实例得分并在巡检信息页面展示,通过得分排序即可快速发现风险实例。

实例综合得分巡检排名表格

ECS 资源大盘: 实时展示所有 Redis-Proxy 和 Redis-Server 所在 ECS 的重要指标,通过排序快速浏览各 ECS 的 CPU 使用率、内存使用率、IOPS 使用率、磁盘读取/写入、上传/下载带宽等。

自动巡检工具: 定期检查所有实例的配置、节点数量等基本信息,对从节点缺失、可用区不一致、节点配置不一致等异常情况进行提示。

故障演练

为了提高自建 Redis 系统在异常场景下的可用性,并检验各异常场景下的恢复时间,团队不定期进行多次故障演练。

演练覆盖所有组件在 ECS、网络、磁盘等出现故障的场景,以及多个组件同时出现故障的组合场景。经过故障演练检验,自建 Redis 的 Redis-Server 主节点故障恢复时间约 12 秒,Redis-Proxy 故障业务恢复时间在 5 秒以内。

六、总结

本文详细介绍了自建 Redis 的架构和现有重要特性。团队仍在持续迭代优化、丰富系统能力,为业务提供功能更强大、性能更优异的分布式缓存系统。未来迭代方向可能包括:

  • 目前 Redis-Server 为兼容云上版本和分布式架构做了较多定制,尚未使用最新社区版本,未来计划升级到 Redis 7.0 等新版本。
  • 热 Key 访问一直是 Redis 使用中对业务影响较大的问题,未来考虑支持热 Key 统计与读热 Key 本地缓存。
  • Golang 版本 Proxy 在高 QPS 请求下,GC 是性能提升的瓶颈之一,未来考虑使用 Rust 重构 Proxy。



上一篇:异地多活架构怎么实现?从单机到同城双活、两地三中心演进
下一篇:MySQL MVCC原理详解:版本链、undo log与Read View可见性规则
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-10-8 02:34 , Processed in 0.073885 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表