集群方案,Redis集群方案计算

必赢365net手机版 12

redis 集群方案主要有两类,一是使用类 codis
的架构,按组划分,实例之间互相独立;
另一套是基于官方的 redis cluster 的方案;下面分别聊聊这两种方案;

本文针对Redis以及redis的几种集群方案的调研日期在2016年8月,后续如果各框架有更新与本文不符,请自行甄别。

类 codis 架构

必赢365net手机版 1

这套架构的特点:

  • 分片算法:基于 slot hash桶;
  • 分片实例之间相互独立,每组 一个master 实例和多个slave;
  • 路由信息存放到第三方存储组件,如 zookeeper 或etcd
  • 旁路组件探活

使用这套方案的公司:
阿里云: ApsaraCache, RedisLabs、京东、百度等

Redis回顾

codis

slots 方案:划分了 1024个slot, slots 信息在 proxy层感知; redis
进程中维护本实例上的所有key的一个slot map;

迁移过程中的读写冲突处理:
最小迁移单位为key;
访问逻辑都是先访问 src 节点,再根据结果判断是否需要进一步访问 target
节点;

  • 访问的 key 还未被迁移:读写请求访问 src 节点,处理后访问:
  • 访问的 key 正在迁移:读请求访问 src
    节点后直接返回;写请求无法处理,返回 retry
  • 访问的 key 已被迁移(或不存在):读写请求访问 src 节点,收到 moved
    回复,继续访问 target 节点处理

Redis支持的数据结构

  • 字符串(String)
  • 哈希(Hash)
  • 列表(List)
  • 集合(Set)
  • 有序集合(Sorted Set)
    • 支持针对score作范围查询
  • 位数组
  • HyperLogLog
    • 做基数统计的算法

阿里云

AparaCache
的单机版已开源(开源版本中不包含slot等实现),集群方案细节未知;ApsaraCache

Redis支持的操作

  • 基本操作
    • Set get add push pop…
  • 发布/订阅
  • Pipeline操作
  • 事务
    • 事务支持不完整。不提供回滚命令。
  • ……

百度 BDRP 2.0

主要组件:
proxy,基于twemproxy 改造,实现了动态路由表;
redis内核: 基于2.x 实现的slots 方案;
metaserver:基于redis实现,包含的功能:拓扑信息的存储 & 探活;
最多支持1000个节点;

slot 方案:
redis 内核中对db划分,做了16384个db; 每个请求到来,首先做db选择;

数据迁移实现:
数据迁移的时候,最小迁移单位是slot,迁移中整个slot
处于阻塞状态,只支持读请求,不支持写请求;
对比 官方 redis cluster/ codis
的按key粒度进行迁移的方案:按key迁移对用户请求更为友好,但迁移速度较慢;这个按slot进行迁移的方案速度更快;

Redis适用场景

  • KV存储
  • 缓存(ttl LRU…)
    • Lru是redis达到maxmemory之后,可选的key删除策略。
  • 消息中间件
  • 分布式锁
  • ……

京东

主要组件:
proxy: 自主实现,基于 golang 开发;
redis内核:基于 redis 2.8
configServer(cfs)组件:配置信息存放;
scala组件:用于触发部署、新建、扩容等请求;
mysql:最终所有的元信息及配置的存储;
sentinal(golang实现):哨兵,用于监控proxy和redis实例,redis实例失败后触发切换;

slot 方案实现:
在内存中维护了slots的map映射表;

数据迁移:
基于 slots 粒度进行迁移;
scala组件向dst实例发送命令告知会接受某个slot;
dst 向 src
发送命令请求迁移,src开启一个线程来做数据的dump,将这个slot的数据整块dump发送到dst(未加锁,只读操作)
写请求会开辟一块缓冲区,所有的写请求除了写原有数据区域,同时双写到缓冲区中。
当一个slot迁移完成后,把这个缓冲区的数据都传到dst,当缓冲区为空时,更改本分片slot规则,不再拥有该slot,后续再请求这个slot的key返回moved;
上层proxy会保存两份路由表,当该slot 请求目标实例得到 move
结果后,更新拓扑;

跨机房:跨机房使用主从部署结构;没有多活,异地机房作为slave;

redis集群实现方式

基于官方 redis cluster 的方案

必赢365net手机版 2

和上一套方案比,所有功能都集成在 redis cluster
中,路由分片、拓扑信息的存储、探活都在redis cluster中实现;各实例间通过
gossip
通信;这样的好处是简单,依赖的组件少,应对400个节点以内的场景没有问题(按单实例8w
read qps来计算,能够支持 200 * 8 = 1600w
的读多写少的场景);但当需要支持更大的规模时,由于使用
gossip协议导致协议之间的通信消耗太大,redis cluster 不再合适;

使用这套方案的有:AWS, 百度贴吧

实现基础——分区

  • 分区是分割数据到多个Redis实例的处理过程,因此每个实例只保存key的一个子集。
  • 通过利用多台计算机内存的和值,允许我们构造更大的数据库。
  • 通过多核和多台计算机,允许我们扩展计算能力;通过多台计算机和网络适配器,允许我们扩展网络带宽。

官方 redis cluster

数据迁移过程:
基于 key粒度的数据迁移;
迁移过程的读写冲突处理:
从A 迁移到 B;

  • 访问的 key 所属slot 不在节点 A 上时,返回 MOVED 转向,client
    再次请求B;
  • 访问的 key 所属 slot 在节点 A 上,但 key 不在 A上, 返回 ASK
    转向,client再次请求B;
  • 访问的 key 所属slot 在A上,且key在 A上,直接处理;(同步迁移场景:该
    key正在迁移,则阻塞)

集群的几种实现方式

  • 客户端分片
  • 基于代理的分片
  • 路由查询

AWS ElasticCache

ElasticCache 支持主从和集群版、支持读写分离;
集群版用的是开源的Redis Cluster,未做深度定制;

客户端分片

  • 由客户端决定key写入或者读取的节点。
  • 包括jedis在内的一些客户端,实现了客户端分片机制。

原理如下所示:

必赢365net手机版 3

client-partition

特性

  • 优点
    • 简单,性能高。
  • 缺点
    • 业务逻辑与数据存储逻辑耦合
    • 可运维性差
    • 多业务各自使用redis,集群资源难以管理
    • 不支持动态增删节点

百度贴吧的ksarch-saas:

基于redis cluster + twemproxy 实现;后被 BDRP 吞并;
twemproxy 实现了 smart client 功能;使用 redis cluster后还加一层
proxy的好处:

  1. 对client友好,不需要client都升级为smart
    client;(否则,所有语言client 都需要支持一遍)
  2. 加一层proxy可以做更多平台策略;比如在proxy可做
    大key、热key的监控、慢查询的请求监控、以及接入控制、请求过滤等;

即将发布的 redis 5.0 中有个 feature,作者计划给 redis
cluster加一个proxy。

ksarch-saas 对 twemproxy的改造已开源:

基于代理的分片

  • 客户端发送请求到一个代理,代理解析客户端的数据,将请求转发至正确的节点,然后将结果回复给客户端。
  • 开源方案
    • Twemproxy
    • codis

基本原理如下所示:

必赢365net手机版 4

proxy-based-partition

特性

  • 透明接入
    • 业务程序不用关心后端Redis实例,切换成本低。
  • Proxy 的逻辑和存储的逻辑是隔离的。
  • 代理层多了一次转发,性能有所损耗。

路由查询

  • 将请求发送到任意节点,接收到请求的节点会将查询请求发送到正确的节点上执行。
  • 开源方案
    • Redis-cluster

基本原理如下所示:

必赢365net手机版 5

query-routing

集群的挑战

  • 涉及多个key的操作通常是不被支持的。
    • 举例来说,当两个set映射到不同的redis实例上时,你就不能对这两个set执行交集操作。
  • 涉及多个key的redis事务不能使用。
  • 不能保证集群内的数据均衡。
    • 分区的粒度是key,如果某个key的值是巨大的set、list,无法进行拆分。
  • 增加或删除容量也比较复杂。
    • redis集群需要支持在运行时增加、删除节点的透明数据平衡的能力。

redis集群各种方案原理

Twemproxy

  • Proxy-based
  • twtter开源,C语言编写,单线程。
  • 支持 Redis 或 Memcached 作为后端存储。

Twemproxy高可用部署架构

必赢365net手机版 6

Twemproxy特性

  • 支持失败节点自动删除
    • 与redis的长连接,连接复用,连接数可配置
  • 自动分片到后端多个redis实例上
    • 多种hash算法:能够使用不同的分片策略和散列函数
    • 支持一致性hash,但是使用DHT之后,从集群中摘除节点时,不会进行rehash操作
    • 可以设置后端实例的权重
  • 支持redis pipelining 操作
  • 支持状态监控
  • 支持select切换数据库

Twemproxy不足

  • 性能低:代理层损耗 && 本身效率低下
  • Redis功能支持不完善
    • 不支持针对多个值的操作,比如取sets的子交并补等(MGET 和 DEL
      除外)
    • 不支持Redis的事务操作
    • 出错提示还不够完善
  • 集群功能不够完善
    • 仅作为代理层使用
    • 本身不提供动态扩容,透明数据迁移等功能
  • 失去维护
    • 最近一次提交在一年之前。

Twitter内部已经不再使用。

redis-cluster

  • redis官网推出,可线性扩展到1000个节点
  • 无中心架构
  • 一致性哈希思想
  • 客户端直连redis服务,免去了proxy代理的损耗

Redis Cluster模型

必赢365net手机版 7

redis-cluster architecture

Redis-cluster原理

  • Hash slot。
    • key的空间被分到16384个hash slot里;
    • 计算key属于哪个slot,CRC16(key) & 16384。
  • 集群内的每个redis实例监听两个tcp端口,6379(默认)用于服务客户端查询,16379(默认服务端口 +
    10000)用于集群内部通信。
  • 节点间状态同步:gossip协议,最终一致性。节点间通信使用轻量的二进制协议,减少带宽占用。

Redis-cluster请求路由方式

  • redis-cluster借助客户端实现了混合形式的路由查询
    查询路由并非直接从一个redis节点到另外一个redis,而是借助客户端转发到正确的节点。根据客户端的实现方式,可以分为以下两种:

    • dummy client
    • smart client
  • 包括Jedis在内的许多redis client,已经实现了对Redis Cluster的支持。

查询路由的流程如下所示:

必赢365net手机版 8

query router of redis cluster

Redis cluster采用这种架构的考虑:

  • 减少redis实现的复杂度
  • 降低客户端等待的时间。Smart client可以在客户端缓存 slot 与
    redis节点的映射关系,当接收到 MOVED
    响应时,会修改缓存中的映射关系。请求时会直接发送到正确的节点上,减少一次交互。

Redis Cluster特性

  • 高性能
  • 支持动态扩容,对业务透明
  • 必赢365net手机版,具备Sentinel的监控和自动Failover能力

Redis Cluster不足

  • 官方未提供图形管理工具,运维比较复杂
    • 比如数据迁移,纯手动操作,先分配slot,再将slot中对应的key迁移至新的节点。
  • 要求客户端必须支持cluster协议
  • Redis命令支持不完整
    • 对于批量的指令,如mget支持不完整;不支持事务;不支持数据库切换,只能使用0号数据库……
  • 集群管理与数据存储耦合
    • 比如如果集群管理有bug,需要升级整个redis。

Codis

  • 豌豆荚开源的proxy-based的redis集群方案
  • 支持透明的扩/缩容
  • 运维友好
    • GUI监控界面和管理工具
  • 同类产品中最全面的redis命令支持

Codis部署拓扑

必赢365net手机版 9

Codis部署拓扑

Codis数据存储

  • 数据根据key分布到1024个slot内
  • Key的slotid计算方法 crc32(key) % 1024
  • 每个 codis-server 负责一部分数据
  • 比如后端有3组codis-server,每个server负责的slot范围可以这样设置:
    • group0 0-300
    • group1 301-600
    • group2 601-1023

Codis模块简介

  • Codis Server
    • 基于 redis-2.8.21 分支开发。增加了额外的数据结构,以支持 slot
      有关的操作以及数据迁移指令。
  • Codis Proxy
    • 客户端连接的 Redis 代理服务, 实现了 Redis 协议。
    • 对于同一个业务集群而言,可以同时部署多个 codis-proxy 实例
    • 不同 codis-proxy 之间由 codis-dashboard 保证状态同步。
  • Codis Dashboard
    • 集群管理工具,支持 codis-proxy、codis-server
      的添加、删除,以及据迁移等操作。
    • 所有对集群的修改都必须通过 codis-dashboard 完成。
  • Codis Admin
    • 集群管理的命令行工具。
    • 可用于控制 codis-proxy、codis-dashboard 状态以及访问外部存储。
  • Codis FE
    • 集群管理界面。
  • Codis HA
    • 为集群提供高可用。
    • 依赖 codis-dashboard 实例,自动抓取集群各个组件的状态;
    • 会根据当前集群状态自动生成主从切换策略,并在需要时通过
      codis-dashboard 完成主从切换。
  • Storage
    • 为集群状态提供外部存储。
    • 目前仅提供了 Zookeeper 和 Etcd 两种实现,但是提供了抽象的
      interface 可自行扩展。

Codis主从切换

  • Codis-HA:自动切换主从的工具。
  • 通过RESTful api从 codis-dashboard 中拉取集群状态
  • 默认以 5s 为周期
  • 该工具会在检测到 master
    挂掉的时候主动应用主从切换策略,向codis-dashboard发送主从切换命令。
  • 对自动主从切换的支持比较弱
    • 主从切换的限制较多,必须在系统其他组件状态健康,且距离上次主从同步数据在一定时间间隔内才可以执行。
    • 多slave场景,提升其中的一个slave为master,其他的slave仍然会从旧的master同步数据,需要管理员手动操作。

Codis数据迁移流程

  • 前提:Codis单条数据迁移是原子操作
  • 单条数据迁移过程:
    • 随机选取指定 slot 中的一个 <K,V>
    • 将这个<K,V>传输给另外一个 codis-server
    • 传输成功后,把本地的这个 <K,V>删除

迁移过程如下所示:

必赢365net手机版 10

迁移过程中,Codis-dashboard与proxy通过zk通信,路由表信息全部存放在zk,保证所有proxy的视图一致。
Codis如何保证数据迁移过程的正确及透明?

  • codis-config 在实际修改slot状态之前,会确保所有的 proxy
    收到这个迁移请求。
  • 迁移过程中, 如果客户端请求 slot 的 key 数据,proxy
    会将请求转发到group2上。

    • proxy会先在group1上强行执行一次 MIGRATE key
      将这个键值提前迁移过来,
    • 然后再到group2上正常读取

Codis VS Redis

对比参数 Codis Redis-cluster
Redis版本 基于2.8分支开发 >= 3.0
部署 较复杂。 简单
运维 Dashboard,运维方便。 运维人员手动通过命令操作。
监控 可在Dashboard里监控当前redis-server节点情况,较为便捷。 不提供监控功能。
组织架构 Proxy-Based, 类中心化架构,集群管理层与存储层解耦。 P2P模型,gossip协议负责集群内部通信。去中心化
伸缩性 支持动态伸缩。 支持动态伸缩
主节点失效处理 自动选主。 自动选主。
数据迁移 简单。支持透明迁移。 需要运维人员手动操作。支持透明迁移。
升级 基于redis 2.8分支开发,后续升级不能保证;Redis-server必须是此版本的codis,无法使用新版本redis的增强特性。 Redis官方推出,后续升级可保证。
可靠性 经过线上服务验证,可靠性较高。 新推出,坑会比较多。遇到bug之后需要等官网升级。
  1. 理论上,redis-cluster的性能更高,单次请求的延时低。另外,经过实测,两种架构后端单台redis-server的条件下,TPS基本没有差别。
  2. Codis的高可用依赖jodis,或者使用LVS进行高可用部署。

我们公司选择Codis的原因

  • Redis-cluster没有成熟的应用案例
  • Codis支持的命令更加丰富
  • 迁移至redis
    cluster需要修改现有实现;而迁移到codis没这么麻烦,只要使用的redis命令在codis支持的范围之内,只要修改一下配置即可接入。
  • Codis提供的运维工具更加友好

Codis简单压测

单台Codis Server压测结果

必赢365net手机版 11

三台Codis-Server的集群压测结果

必赢365net手机版 12

压测结论

  • 针对codis集群压测过程中,后端codis server平均CPU占用约为70%~80%。
  • 单台codis的TPS在6w~7w左右,集群的TPS在17w左右,可以达到近乎线性扩展的能力
  • 测试期间后台codis-server的负载没有跑满,仍然具有继续压测的潜力。
  • 测试期间proxy机器负载低,可以支撑更多后端codis server实例。

使用codis注意事项

  • 不支持的命令
    • 不支持的命令列表
  • 防止key冲突
    • 建议现有业务接入codis时,加入项目前缀以作区分。
  • 使用spring data
    redis操作codis时,只能使用RedisTemplate系列接口,Cache系列接口不可用

    • Cache系列的接口使用了redis的事务指令,事务在Codis以及Redis
      Cluster中均未提供支持。
  • 避免key value巨大的数据
    • 吞吐量提升不明显
    • 可能造成各codis实例资源占用不均衡

Leave a Comment.