Redis记录
概述
Redis 是包含多种数据结构、支持网络、基于内存、可选持久性的键值对存储数据库,它基于内存运行,性能高效。而公司自研实现的 Redis 集群方案为 Alchemy 架构,可支持更大的集群,及更快更方便的集群拓扑变更,保障业务的高可用。目前 Redis 线上集群已超过 3w+,服务包括头条、抖音、 TikTok、广告、电商、IES、社交、推荐、关注、评论、用户画像等大部分业务
适用场景
公司自研实现的 Alchemy 架构的 Redis 集群适用于如下业务场景:
- 业务对数据实时性和读写性能要求高,对数据延迟敏感。
- 要求有一定的分区容错性,但不要求数据强一致性。
- 事务需求较少,但对弱数据结构的存储和扩展能力需求较高,Redis 对事务支持能力较弱,是 KV 模型的存储。
- 单次请求的通量数据不大,数据模型不复杂。对于String 类型数据,KV 大小超过 10KB 即为大 key,最大不应超过 512MiB;而对非 String 类型(如 Hash、Set、Zset、List 等)数据,元素长度超过 5000 个即为大 Key,最大不应超过 8192 个,Value 最大长度不应超过 1MiB。
基础概念
术语 | 说明 |
---|---|
Alchemy架构 | Redis 主推的架构类型,相关介绍参考Redis 基本架构介绍。 |
RC架构 | 表示 Redis Cluster 架构,当前架构演进默认采用 Alchemy 架构。 |
经典模式 | 服务实例部署于物理机。 |
云原生模式 | 依托于 K8S ,服务容器化部署,利用其可靠的自动化手段,更好地解决平滑升级、故障自愈、资源隔离等痛点问题。 |
机房 | 指服务所在的数据中心环境,目前国内主要有 LF、HL、LQ等 ,国外有 sg1、Useast-red、US-EAST 等。 |
分片 | 跟Redis社区一样,Redis 共 16384 个槽,分片即对这 16384 个槽进行划分,每个分片存储一定量的哈希槽,通常一个分片为一主一备双实例 |
Alchemy 架构
字节云 Redis 经过架构演进,历史上采用了 Redis cluster架构,codis 架构,以及到现在的 Alchemy 架构,本文主要介绍 Alchemy 架构。 Alchemy 架构是基于 Redis 5.0,自研实现的 Redis 中心化的集群方案。包含组件 Redis server,proxy 和 ConfigServer,与 RC 架构的区别是通过 ConfigServer 来维护集群的拓扑变更,以支持更大的集群,及更快更方便的集群拓扑变更。
组件
Alchemy proxy
proxy是无状态的,主要有以下作用:
- Proxy初始化时会从ConfigServer获取集群信息,与ConfigServer交互,更新配置。
- Proxy会与ConfigServer进行定期心跳的探测,保证proxy实例正常,剔除异常的proxy实例。
- 负责负载均衡、鉴权,限速等模块。
- 响应 Client SDK的请求,把请求转发给合适的后端 Redis -server,这里请求转发是基于key的hash分布(crc16(key)%16384),找到key所在的server实例进行读写,并返回请求结果给client。
Redis server
Redis server主要是作为 Redis 引擎,存储数据,处理读写请求,主要有以下作用:
- 从ConfigServer接收管理性的信息,管理 slot 和主从迁移。
- 接收来自 Proxy 关于数据的读写命令,并返回结果。
从图中可以看出 Redis server有primary 和 secondary两个实例,一组primary和secondary就是一个分片,一个分片里存储一定比例的slot,而用户写入的key会根据hash分布(crc16(key)%16384)散列到不同的slot的,也就存到了不同的分片中。
Client
字节云 Redis 支持 Redis 协议接入,当前提供 go、python、c++ db2、java 等语言的 sdk,各 sdk 文档可参考SDK 参考章节。
这里的 sdk 大多基于社区的 sdk 进行封装,主要增加了 Consul,GPDR/ZTI 鉴权,Metrics等模块,访问字节云 Redis 建议使用我们提供的 sdk,如果访问的是非字节云 Redis 请使用社区提供的 sdk。
ConfigServer
由于字节云 Redis 提供的是中心化的集群架构,因此这里需要有一个组件,即 ConfigServer 来进行如下工作:
- 元信息管理。
- Topom构建。
- 集群高可用。
- 运维管理。
ConfigServer 主要负责响应平台的创建 / 扩容 / 下线请求,并将 Redis 的元信息持久化到 ETCD 中,对 Redis 进行探活、主从切换等。
ETCD
主要与 ConfigServer 交互,作为元信息存储组件,存储 Redis 的元信息。
读写流程
以常见的cn三机房同步架构为例,详细介绍 Alchemy 架构下的读写流程,cn三机房同步架构以 lf 为主机房(不排除后续主机房变更为其他机房,例如 lf 机房裁撤,主机房就需要换成别的机房)。
- 用户的读写请求会先到 Redis 的 Proxy。用户通过 Redis SDK 访问 Redis 服务,而 SDK 通过 Consul 发现 Redis 服务的 Proxy IP。若代码中的 PSM 未添加 service.${dc} 后缀指定机房,则 Consul 默认发现本机房的 IP,即在 lf 机房发起的请求会访问 lf 的 Proxy。建议尽量避免跨机房访问。
- Proxy 会根据如下规则将读写请求转发到相应机房的 Redis 实例。
读请求:由于分片的每个实例都可以进行读,因此读请求会到本机房(lf到lf,hl到hl,lq到lq),并且每个机房的primary和secondary实例随机接受读请求。
写请求:仅主机房的主实例可写,因此从lf写入的话会直接写到主机房lf的primary实例,从hl和lq写入,会路由到主机房lf的primary实例上写入,此时就会有跨机房写入的一个延迟(ms级别,用户侧感知在3ms左右,受网络情况可能会更大,当前无主从延迟的监控)。
关键技术
- 使用中心化的元信息存储,使用 Raft 来保证元信息的强一致性和 ConfigServer 的可靠性。
- 使用 AsyncMigrate 降低 Redis 数据迁移的阻塞,Async 使用了额外线程来处理,可减少因为 Redis 单线程带来的阻塞问题 。
- 使用 Aof binlog 作为多机房同步,减少网络和 CPU 开销