Redis

Posted by Shenpotato on December 31, 2024

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 来维护集群的拓扑变更,以支持更大的集群,及更快更方便的集群拓扑变更。

image-20241231113746782

组件

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 机房裁撤,主机房就需要换成别的机房)。

img

  1. 用户的读写请求会先到 Redis 的 Proxy。用户通过 Redis SDK 访问 Redis 服务,而 SDK 通过 Consul 发现 Redis 服务的 Proxy IP。若代码中的 PSM 未添加 service.${dc} 后缀指定机房,则 Consul 默认发现本机房的 IP,即在 lf 机房发起的请求会访问 lf 的 Proxy。建议尽量避免跨机房访问。
  2. 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 开销