searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

redis proxy设计

2024-07-22 08:51:22
18
0

需求背景

需求背景

目前的Redis集群方案如Codis、Twemproxy、Redis Cluster都各有优缺点。其中,Codis和Twemproxy的使用最为典型。然而,Codis已经停止开源维护,并且只支持Redis的特定版本。此外,由于其组件众多,运维部署较为不便。Twemproxy的主要问题在于不支持数据迁移,这使得它难以满足线上需求。

针对以上问题,我们希望实现一个支持redis协议的集群方案,以解决上面存在的问题。

技术背景

我们将在twemproxy的开源版本的基础上,实现redis的集群方案。twemproxy的整体架构如下:

但当前twemproxy存在一些问题,如不支持数据迁移、不支持配置热加载、监控缺失等问题,在该开源基础上,主要解决以下问题:

  1. 数据分片的问题
  2. 数据迁移的问题
  3. 高可用的问题
  4. 高性能的问题
  5. 部署的易用性问题

设计目标

高可用

解决后端redis节点出现故障时,能够自动进行故障检测和恢复,实现故障自愈。

数据动态迁移

数据迁移主要是为了实现数据的动态扩缩容。当后端Redis实例的数据量达到阈值或低于阈值时,可能需要进行扩缩容,以满足业务的发展需求或节省资源。

高性能

redis的特点之一就是高性能,所以redis proxy的设计目标之一就是要高性能,高效完成redis请求的转发处理

监控

各个组件的情况能够及时上报监控平台并进行监控

易用性

这个暂时不是重点,可以采用ansible进行一键部署即可

整体设计

总体设计

总体架构图如下:

  1. slot:槽位,跟codis中使用的槽位一个概念,默认1024个槽位,一个key通过crc哈希映射到一个slot,相当于一个slot负责一部分数据
  2. redis group:一个由redis主备实例组成的集群,一个主,多个备,一个redis group负责一部分slot,用户的redis请求根据key所属的slot会被路由到某个redis group,然后由该主备实例提供服务
  3. 负载均衡层:对外提供一个vip给用户使用即可,业界方案可以用公司内部的负载均衡方案或者由keepalived/haproxy也可实现,不是本文重点
  4. etcd:元数据管理,保存数据迁移任务、slot映射关系、redis group下面的主备实例ip信息等
  5. configSvr: 管理服务,负责管理集群中各个组件,如管理redis proxy、管理redis group等、采用多可用区部署,此外还负责接收dashboard请求、redis server的HA、处理数据迁移等,基于etcd服务发现实现高可用以及使用raft协议实现HA
  6. redis proxy:redis的代理,无状态服务,接收redis的请求,将请求转发到后端redis节点,基于开源twemproxy改造而来,采用master worker机制实现高性能,后期融入dpdk来实现高性能转发

总体流程

访问redis流程:用户访问vip,vip转发请求到某个proxy节点,proxy节点根据key的请求计算得到slot,再根据slot到redis group的映射关系,将请求转发到某个redis group中去处理

HA流程:configSvr集群定期对redis group中的redis实例进行HA检测,发现故障,则通过raft协议实现故障转移和恢复

数据迁移:调用configSvr发起数据迁移任务,迁移任务入etcd,configSvr从etcd取迁移任务并进行并发的数据迁移

监控采集上报:redis proxy和configSvr分别实现exporter接口,开源promethus定期拉取接口进行监控上报即可,可采用prometheus/pushgateway + alertmanager + grafana实现监控数据拉取,展示和告警

详细设计

下面针对每个组件以及组件之间数据交互详细设计下。

开发约定

configSvr: 集群配置管理服务,负责集群中各个组件的管理、HA、数据迁移等

slot:槽位,抽象的一个概念,一个key会属于一个slot,一个slot会包含多个key

redis group: redis主备实例组成的redis实例组,一般由一主多备组成,一个redis group负责一部分slot

HA: 高可用故障检测和恢复,由configSvr定期对redis group中的server进行故障检测,发生故障,自动进行故障恢复,即故障自愈

raft协议:分布式共识协议,用于多个节点共识的一致

etcd:一种开源的分布式统一键值存储,用于分布式系统或计算机集群的共享配置、服务发现和的调度协调,这里用来进行configSvr的服务发现以及元数据管理,如slot映射关系,slot迁移任务数据等

redis proxy: 集群redis代理节点,负责接收请求并转发处理

功能实现

数据结构设计

slot到redis group的映射关系:

type action struct {
    Index     int 
    State     string // 迁移的状态:1:准备状态 2:待迁移 3: 迁移中  4: 迁移完成
    TargetGroupId  int   // 目标迁移的redis group id
    UpdatedAt int64
}

type slotIdInfo struct {
		SlotID  int
    GroupID int
    Action action
}

redis group到主备实例的映射关系:

type Server struct {
    hostIp  string
    port  int
}
type serverGroupInfo struct {
		GroupID int
    GroupName string
    Servers []Server
}

存储设计

使用etcd来保存,slot到group的映射关系,key是一个slot路径,value是上面数据结构的json字符串即可,如下:

/redis-cluster/slot-to-group-mapping/slot1 -> {"group_id": "redis-group1", "slogId": "slot1", "action":{}"}
/redis-cluster/slot-to-group-mapping/slot2 -> {"group_id": "redis-group2", "slogId": "slot2", "action":{}}
/redis-cluster/slot-to-group-mapping/slot3 -> {"group_id": "redis-group1", "slogId": "slot3", "action":{}}

redis group对应的数据存储,key是group id, values是一个json字符串,保存了主备实例信息,如下:

/redis-cluster/group-instances/redis-group1 -> {
    "master": "192.168.1.101:6379",
    "replicas": [
        "192.168.1.102:6379",
        "192.168.1.103:6379"
    ]
}
/redis-cluster/group-instances/redis-group2 -> {
    "master": "192.168.1.104:6379",
    "replicas": [
        "192.168.1.105:6379",
        "192.168.1.106:6379"
    ]
}

redis proxy组件设计

设计思想:基于twemproxy开源基础上,实现master-多worker进程模型,master负责管理多个worker子进程,两者通过管道通信,多个worker子进程使用SO_REUSEPORT特性同时监听端口进行服务,由内核层面进行负载均衡的请求转发,并实现一些特性:

  1. 配置热加载:对外提供http配置更新接口,实现配置的热更新
  2. 支持按slot进行分片:维护slot映射数据以及redis group的配置数据,转发请求按slot转发到后端的节点
  3. 支持woker进程异常,自动拉起等
  4. worker子进程数可配置:根据需要可配置多个worker子进程来处理请求,实现高并发
  5. 监控添加exporter接口,监控数据采集完善

配置更新逻辑:配置数据维护在etcd中,configserver检测到etcd中配置数据有变动,则从etcd获取到最新配置,调用proxy的http接口更新配置,父进程收到配置,写本地文件,发信号给子进程进行更新,即

  1. 调用http接口更新配置:configSvr检测到配置变动,调用redis proxy的http接口更新配置
  2. redis proxy Update更新本地磁盘配置文件
  3. Signal给子进程
  4. 子进程Reload加载配置文件

configSvr组件设计

开发语言:go语言开发

  • 组件管理:redis group管理、slot和redis group配置管理、redis proxy管理等
  • dashboard服务:api服务,提供dashboard接口对外提供服务
  • HA保障:redis server的HA,redis proxy HA
  • 动态扩缩容:slot槽位数据迁移、redis group上下线等
  • 协议:raft实现高可用以及HA

数据迁移的设计

数据迁移逻辑:通过configSvr提交数据迁移任务,任务数据入etcd,configSvr检测到数据迁移任务,更新proxy的配置信息,利用多协程调用redis的接口对目标slot进行迁移即可,数据迁移完成更新配置信息 redis proxy在迁移过程中的读写处理:当前处理的key所属的slot正在迁移,同步迁移时则调用 SLOTSMGRTTAGSLOT 命令将这个key迁移完成再返回给客户端,同时缓存该key已迁移,下次 访问即请求到新的redis group

HA流程的设计

HA保障逻辑:多个configSvr定期探测redis server接口,发现master节点故障,则利用raft协议选举leader进行故障恢复,具体过程是多个configSvr确认某个master节点故障,由leader进行故障恢复,具体逻辑是leader选一个最佳备节点提升为主节点,并更新redis group信息到etcd中,调用proxy的接口更新配置即可,跟redis sentinel有点类似,不过configSvr之间是直接通信,效率更高

监控设计

各个组件实现exporter接口即可

方案优缺点

优点:

  • 相比twemproxy的优点:继承Twemproxy的优点,支持数据迁移、配置reload、提供dashboard接口可运维
  • 相比codis的优点:基本具备codis的优点,无需改造redis,兼容开源的redis版本,可适配各种类redis产品,部署相比更简单,configSvr高效实现HA
  • master worker进程模型,可横向扩展子worker数
  • c语言开发,更加偏向底层,后续可尝试采用io uring或者dpdk来提高性能

缺点:

  • proxy会带来额外的网络开销,会有性能损失
  • 维护多个组件:etcd,configSvr

部署拓扑

redis proxy部署:多机器部署

redis server主备:不同机房主备异地部署

configSvr: 多可用区部署

etcd:部署etcd集群即可

0条评论
0 / 1000
9****m
15文章数
1粉丝数
9****m
15 文章 | 1 粉丝
原创

redis proxy设计

2024-07-22 08:51:22
18
0

需求背景

需求背景

目前的Redis集群方案如Codis、Twemproxy、Redis Cluster都各有优缺点。其中,Codis和Twemproxy的使用最为典型。然而,Codis已经停止开源维护,并且只支持Redis的特定版本。此外,由于其组件众多,运维部署较为不便。Twemproxy的主要问题在于不支持数据迁移,这使得它难以满足线上需求。

针对以上问题,我们希望实现一个支持redis协议的集群方案,以解决上面存在的问题。

技术背景

我们将在twemproxy的开源版本的基础上,实现redis的集群方案。twemproxy的整体架构如下:

但当前twemproxy存在一些问题,如不支持数据迁移、不支持配置热加载、监控缺失等问题,在该开源基础上,主要解决以下问题:

  1. 数据分片的问题
  2. 数据迁移的问题
  3. 高可用的问题
  4. 高性能的问题
  5. 部署的易用性问题

设计目标

高可用

解决后端redis节点出现故障时,能够自动进行故障检测和恢复,实现故障自愈。

数据动态迁移

数据迁移主要是为了实现数据的动态扩缩容。当后端Redis实例的数据量达到阈值或低于阈值时,可能需要进行扩缩容,以满足业务的发展需求或节省资源。

高性能

redis的特点之一就是高性能,所以redis proxy的设计目标之一就是要高性能,高效完成redis请求的转发处理

监控

各个组件的情况能够及时上报监控平台并进行监控

易用性

这个暂时不是重点,可以采用ansible进行一键部署即可

整体设计

总体设计

总体架构图如下:

  1. slot:槽位,跟codis中使用的槽位一个概念,默认1024个槽位,一个key通过crc哈希映射到一个slot,相当于一个slot负责一部分数据
  2. redis group:一个由redis主备实例组成的集群,一个主,多个备,一个redis group负责一部分slot,用户的redis请求根据key所属的slot会被路由到某个redis group,然后由该主备实例提供服务
  3. 负载均衡层:对外提供一个vip给用户使用即可,业界方案可以用公司内部的负载均衡方案或者由keepalived/haproxy也可实现,不是本文重点
  4. etcd:元数据管理,保存数据迁移任务、slot映射关系、redis group下面的主备实例ip信息等
  5. configSvr: 管理服务,负责管理集群中各个组件,如管理redis proxy、管理redis group等、采用多可用区部署,此外还负责接收dashboard请求、redis server的HA、处理数据迁移等,基于etcd服务发现实现高可用以及使用raft协议实现HA
  6. redis proxy:redis的代理,无状态服务,接收redis的请求,将请求转发到后端redis节点,基于开源twemproxy改造而来,采用master worker机制实现高性能,后期融入dpdk来实现高性能转发

总体流程

访问redis流程:用户访问vip,vip转发请求到某个proxy节点,proxy节点根据key的请求计算得到slot,再根据slot到redis group的映射关系,将请求转发到某个redis group中去处理

HA流程:configSvr集群定期对redis group中的redis实例进行HA检测,发现故障,则通过raft协议实现故障转移和恢复

数据迁移:调用configSvr发起数据迁移任务,迁移任务入etcd,configSvr从etcd取迁移任务并进行并发的数据迁移

监控采集上报:redis proxy和configSvr分别实现exporter接口,开源promethus定期拉取接口进行监控上报即可,可采用prometheus/pushgateway + alertmanager + grafana实现监控数据拉取,展示和告警

详细设计

下面针对每个组件以及组件之间数据交互详细设计下。

开发约定

configSvr: 集群配置管理服务,负责集群中各个组件的管理、HA、数据迁移等

slot:槽位,抽象的一个概念,一个key会属于一个slot,一个slot会包含多个key

redis group: redis主备实例组成的redis实例组,一般由一主多备组成,一个redis group负责一部分slot

HA: 高可用故障检测和恢复,由configSvr定期对redis group中的server进行故障检测,发生故障,自动进行故障恢复,即故障自愈

raft协议:分布式共识协议,用于多个节点共识的一致

etcd:一种开源的分布式统一键值存储,用于分布式系统或计算机集群的共享配置、服务发现和的调度协调,这里用来进行configSvr的服务发现以及元数据管理,如slot映射关系,slot迁移任务数据等

redis proxy: 集群redis代理节点,负责接收请求并转发处理

功能实现

数据结构设计

slot到redis group的映射关系:

type action struct {
    Index     int 
    State     string // 迁移的状态:1:准备状态 2:待迁移 3: 迁移中  4: 迁移完成
    TargetGroupId  int   // 目标迁移的redis group id
    UpdatedAt int64
}

type slotIdInfo struct {
		SlotID  int
    GroupID int
    Action action
}

redis group到主备实例的映射关系:

type Server struct {
    hostIp  string
    port  int
}
type serverGroupInfo struct {
		GroupID int
    GroupName string
    Servers []Server
}

存储设计

使用etcd来保存,slot到group的映射关系,key是一个slot路径,value是上面数据结构的json字符串即可,如下:

/redis-cluster/slot-to-group-mapping/slot1 -> {"group_id": "redis-group1", "slogId": "slot1", "action":{}"}
/redis-cluster/slot-to-group-mapping/slot2 -> {"group_id": "redis-group2", "slogId": "slot2", "action":{}}
/redis-cluster/slot-to-group-mapping/slot3 -> {"group_id": "redis-group1", "slogId": "slot3", "action":{}}

redis group对应的数据存储,key是group id, values是一个json字符串,保存了主备实例信息,如下:

/redis-cluster/group-instances/redis-group1 -> {
    "master": "192.168.1.101:6379",
    "replicas": [
        "192.168.1.102:6379",
        "192.168.1.103:6379"
    ]
}
/redis-cluster/group-instances/redis-group2 -> {
    "master": "192.168.1.104:6379",
    "replicas": [
        "192.168.1.105:6379",
        "192.168.1.106:6379"
    ]
}

redis proxy组件设计

设计思想:基于twemproxy开源基础上,实现master-多worker进程模型,master负责管理多个worker子进程,两者通过管道通信,多个worker子进程使用SO_REUSEPORT特性同时监听端口进行服务,由内核层面进行负载均衡的请求转发,并实现一些特性:

  1. 配置热加载:对外提供http配置更新接口,实现配置的热更新
  2. 支持按slot进行分片:维护slot映射数据以及redis group的配置数据,转发请求按slot转发到后端的节点
  3. 支持woker进程异常,自动拉起等
  4. worker子进程数可配置:根据需要可配置多个worker子进程来处理请求,实现高并发
  5. 监控添加exporter接口,监控数据采集完善

配置更新逻辑:配置数据维护在etcd中,configserver检测到etcd中配置数据有变动,则从etcd获取到最新配置,调用proxy的http接口更新配置,父进程收到配置,写本地文件,发信号给子进程进行更新,即

  1. 调用http接口更新配置:configSvr检测到配置变动,调用redis proxy的http接口更新配置
  2. redis proxy Update更新本地磁盘配置文件
  3. Signal给子进程
  4. 子进程Reload加载配置文件

configSvr组件设计

开发语言:go语言开发

  • 组件管理:redis group管理、slot和redis group配置管理、redis proxy管理等
  • dashboard服务:api服务,提供dashboard接口对外提供服务
  • HA保障:redis server的HA,redis proxy HA
  • 动态扩缩容:slot槽位数据迁移、redis group上下线等
  • 协议:raft实现高可用以及HA

数据迁移的设计

数据迁移逻辑:通过configSvr提交数据迁移任务,任务数据入etcd,configSvr检测到数据迁移任务,更新proxy的配置信息,利用多协程调用redis的接口对目标slot进行迁移即可,数据迁移完成更新配置信息 redis proxy在迁移过程中的读写处理:当前处理的key所属的slot正在迁移,同步迁移时则调用 SLOTSMGRTTAGSLOT 命令将这个key迁移完成再返回给客户端,同时缓存该key已迁移,下次 访问即请求到新的redis group

HA流程的设计

HA保障逻辑:多个configSvr定期探测redis server接口,发现master节点故障,则利用raft协议选举leader进行故障恢复,具体过程是多个configSvr确认某个master节点故障,由leader进行故障恢复,具体逻辑是leader选一个最佳备节点提升为主节点,并更新redis group信息到etcd中,调用proxy的接口更新配置即可,跟redis sentinel有点类似,不过configSvr之间是直接通信,效率更高

监控设计

各个组件实现exporter接口即可

方案优缺点

优点:

  • 相比twemproxy的优点:继承Twemproxy的优点,支持数据迁移、配置reload、提供dashboard接口可运维
  • 相比codis的优点:基本具备codis的优点,无需改造redis,兼容开源的redis版本,可适配各种类redis产品,部署相比更简单,configSvr高效实现HA
  • master worker进程模型,可横向扩展子worker数
  • c语言开发,更加偏向底层,后续可尝试采用io uring或者dpdk来提高性能

缺点:

  • proxy会带来额外的网络开销,会有性能损失
  • 维护多个组件:etcd,configSvr

部署拓扑

redis proxy部署:多机器部署

redis server主备:不同机房主备异地部署

configSvr: 多可用区部署

etcd:部署etcd集群即可

文章来自个人专栏
系统设计
2 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0