Redis Cluster探索与思考
《Redis Cluster探索与思考》要点: 作者 | 张冬洪责编 | 仲培艺 Redis Cluster的基来源根基理和架构 Redis Cluster是分布式Redis的实现.随着Redis版本的更替,以及各种已知bug的fixed,在稳定性和高可用性上有了很大的提升和进步,越来越多的企业将Redis Cluster实际应用到线上业务中,通过从社区获取到反馈社区的迭代,为Redis Cluster成为一个可靠的企业级开源产品,在简化业务架构和业务逻辑方面都起着积极重要的作用.下面从Redis Cluster的基来源根基理为起点开启Redis Cluster在业界的分析与思考之旅. 基来源根基理Redis Cluster的基来源根基理可以从数据分片、数据迁移、集群通讯、故障检测以及故障转移等方面进行了解,Cluster相关的代码也不是很多,注释也很详细,可自行查看,地址是:https://github.com/antirez/redis/blob/unstable/src/cluster.c.这里由于篇幅的原因,主要从数据分片和数据迁移两方面进行详细介绍: 数据分片 Redis Cluster在设计中没有使用一致性哈希(Consistency Hashing),而是使用数据分片(Sharding)引入哈希槽(hash slot)来实现;一个 Redis Cluster包括16384(0~16383)个哈希槽,存储在Redis Cluster中的所有键都会被映射到这些slot中,集群中的每个键都属于这16384个哈希槽中的一个,集群使用公式slot=CRC16(key)/16384来计算key属于哪个槽,其中CRC16(key)语句用于计算key的CRC16 校验和. 集群中的每个主节点(Master)都负责处理16384个哈希槽中的一部分,当集群处于稳定状态时,每个哈希槽都只由一个主节点进行处理,每个主节点可以有一个到N个从节点(Slave),当主节点出现宕机或网络断线等弗成用时,从节点能自动提升为主节点进行处理. 如图1,ClusterNode数据结构中的slots和numslots属性记录了节点负责处理哪些槽.其中,slot属性是一个二进制位数组(bitarray),其长度为16384/8=2048 Byte,共包括16384个二进制位.集群中的Master节点用bit(0和1)来标识对于某个槽是否拥有.比如,对于编号为1的槽,Master只要判断序列第二位(索引从0开始)的值是不是1即可,时间复杂度为O(1). 图1 ClusterNode数据布局 集群中所有槽的分配信息都保存在ClusterState数据结构的slots数组中,程序要检查槽i是否已经被分配或者找出处理槽i的节点,只需要拜访clusterState.slots[i]的值即可,复杂度也为O(1).ClusterState数据结构如图2所示. 图2 ClusterState数据布局 查找关系如图3所示. 图3 查找关系图 数据迁移 数据迁移可以理解为slot和key的迁移,这个功能很重要,极大地便利了集群做线性扩展,以及实现平滑的扩容或缩容.那么它是一个怎样的实现过程?下面举个例子:现在要将Master A节点中编号为1、2、3的slot迁移到Master B节点中,在slot迁移的中间状态下,slot 1、2、3在Master A节点的状态表现为MIGRATING,在Master B节点的状态表现为IMPORTING. MIGRATING状态 这个状态如图4所示是被迁移slot在当前所在Master A节点中出现的一种状态,预备迁移slot从Mater A到Master B的时候,被迁移slot的状态首先变为MIGRATING状态,当客户端哀求的某个key所属的slot的状态处于MIGRATING状态时,会出现以下几种情况: 图4 slot迁移的中间状态
IMPORTING状态 这个状态如图2所示是被迁移slot在目标Master B节点中出现的一种状态,被迁移slot的状态首先变为IMPORTING状态.在这种状态下的slot对客户端的哀求可能会有下面几种影响:
键空间迁移 这是完成数据迁移的重要一步,键空间迁移是指当满足了slot迁移前提的情况下,通过相关命令将slot 1、2、3中的键空间从Master A节点转移到Master B节点,这个过程由MIGRATE命令经过3步真正完成数据转移.步调示意如图5. 图5 表空间迁移步调 颠末上面三步可以完成键空间数据迁移,然后再将处于MIGRATING和IMPORTING状态的槽变为常态即可,从而完成整个重新分片的过程. 架构实现细节:
Redis Cluster的优势和不敷 优势1. 无中心架构. 2. 数据依照slot存储分布在多个节点,节点间数据共享,可动态调整数据分布. 3. 可扩展性,可线性扩展到1000个节点,节点可动态添加或删除. 4. 高可用性,部分节点弗成用时,集群仍可用.通过增加Slave做standby数据副本,能够实现故障自动failover,节点之间通过gossip协议交换状态信息,用投票机制完成Slave到Master的角色提升. 5. 降低运维本钱,提高系统的扩展性和可用性. 不足1. Client实现复杂,驱动要求实现Smart Client,缓存slots mapping信息并及时更新,提高了开发难度,客户端的不成熟影响业务的稳定性.目前仅JedisCluster相对成熟,异常处理部分还不完善,好比常见的“max redirect exception”. 2. 节点会因为某些原因发生阻塞(阻塞时间大于clutser-node-timeout),被判断下线,这种failover是没有需要的. 3. 数据通过异步复制,不保证数据的强一致性. 4. 多个业务使用同一套集群时,无法根据统计区分冷热数据,资源隔离性较差,容易呈现相互影响的情况. 5. Slave在集群中充当“冷备”,不克不及缓解读压力,当然可以通过SDK的合理设计来提高Slave资源的利用率. Redis Cluster在业界有哪些探索 通过调研了解,目前业界使用Redis Cluster年夜致可以总结为4类: 直连型直连型,又可以称之为经典型或者传统型,是官方的默认使用方式,架构图见图6.这种使用方式的优缺点在上面的介绍中已经有所说明,这里不再过多重复赘述.但值得一提的是,这种方式使用Redis Cluster需要依赖Smart Client,诸如连接维护、缓存路由表、MultiOp和Pipeline的支持都需要在Client上实现,而且很多语言的Client目前都还是没有的(关于Clients的更多介绍请参考https://redis.io/clients).虽然Client能够进行定制化,但有必定的开发难度,客户端的不成熟将直接影响到线上业务的稳定性. 图6 Redis Cluster架构 带Proxy型在Redis Cluster还没有那么稳定的时候,很多公司都已经开始探索分布式Redis的实现了,好比有基于Twemproxy或者Codis的实现,下面举一个唯品会基于Twemproxy架构的例子(不少公司分布式Redis的集群架构都经历过这个阶段),如图7所示. 图7 Redis基于Twemproxy的架构实现 这种架构的优点和缺点也比拟明显. 长处: 1. 后端Sharding逻辑对业务透明,业务方的读写方式和操作单个Redis一致; 2. 可以作为Cache和Storage的Proxy,Proxy的逻辑和Redis资源层的逻辑是隔离的; 3. Proxy层可以用来兼容那些目前还不支持的Clients. 缺点: 1. 结构复杂,运维本钱高; 2. 可扩展性差,进行扩缩容都必要手动干预; 3. failover逻辑需要自己实现,其自己不能支持故障的自动转移; 4. Proxy层多了一次转发,性能有所损耗. 正是因此,我们知道Redis Cluster和基于Twemproxy布局使用中各自的优缺点,于是就出现了下面的这种架构,糅合了二者的优点,尽量规避二者的缺点,架构如图8. 图8 Smart Proxy计划架构 目前业界Smart Proxy的方案了解到的有基于Nginx Proxy和自研的,自研的如饿了么开源部分功能的Corvus,优酷土豆是则通过Nginx来实现,滴滴也在展开基于这种方式的探索.选用Nginx Proxy主要是考虑到Nginx的高性能,包含异步非阻塞处理方式、高效的内存管理、和Redis一样都是基于epoll事件驱动模式等优点.优酷土豆的Redis服务化就是采用这种结构. 长处: 1. 提供一套HTTP Restful接口,隔离底层资源,对客户端完全透明,跨语言挪用变得简单; 2. 升级维护较为容易,维护Redis Cluster,只需平滑升级Proxy; 3. 条理化存储,底层存储做冷热异构存储; 4. 权限控制,Proxy可以通过密钥管理白名单,把一些不合法的哀求都过滤掉,并且也可以对用户哀求的超大value进行控制和过滤; 5. 平安性,可以屏蔽掉一些危险命令,比如keys *、save、flushall等,当然这些也可以在Redis上进行设置; 6. 资源逻辑隔离,根据分歧用户的key加上前缀,来实现动态路由和资源隔离; 7. 监控埋点,对于分歧的接口进行埋点监控. 缺点: 1. Proxy层做了一次转发,性能有所损耗; 2. 增加了运维成本和管理成本,需要对架构和Nginx Proxy的实现细节足够了解,因为Nginx Proxy在批量接口调用高并发下可能会瞬间向Redis Cluster发起几百甚至上千的协程去拜访,导致Redis的连接数或系统负载的不稳定,进而影响集群整体的稳定性. 云服务型这种类型典型的案例就是企业级的PaaS产品,如亚马逊和阿里云提供的Redis Cluster服务,用户无需知道内部的实现细节,只管使用即可,降低了运维和开发成本.当然也有开源的产品,国内如搜狐的CacheCloud,它提供一个Redis云管理平台,实现多种类型(Redis Standalone、Redis Sentinel、Redis Cluster)自动部署,办理Redis实例碎片化现象,提供完善统计、监控、运维功能,减少开发人员的运维成本和误操作,提高机器的利用率,提供灵活的伸缩性,提供方便的接入客户端,更多细节请参考:https://cachecloud.github.io.尽管这还不错,如果是一个新业务,到可以尝试一下,但若对于一个稳定的业务而言,要迁移到CacheCloud上则需要谨慎.如果对分布式框架感兴趣的可以看下Twitter开源的一个实现Memcached和Redis的分布式缓存框架Pelikan,目前国内并没有看到这样的应用案例,它的官网是http://twitter.github.io/pelikan/. 图9 CacheCloud平台架构 自研型这种类型在众多类型中更显得孤独,因为这种类型的方案更多是现象级,仅仅存在于为数不多的具有自研能力的公司中,或者说这种方案都是各公司根据自己的业务模型来进行定制化的.这类产品的一个共同特点是没有使用Redis Cluster的全部功能,只是借鉴了Redis Cluster的某些核心功能,比如说failover和slot的迁移.作为国内使用Redis较早的公司之一,新浪微博就基于内部定制化的Redis版本研发出了微博Redis服务化系统Tribe.它支持动态路由、读写分离(从节点能够处理读哀求)、负载均衡、配置更新、数据聚集(相同前缀的数据落到同一个slot中)、动态扩缩容,以及数据落地存储.同类型的还有百度的BDRP系统. 图10 Tribe系统架构图 Redis Cluster运维开发最佳实践经验
作者简介 张冬洪,微博研发中心高档DBA,Redis中国用户组主席,多年Linux和数据库运维经验,专注于MySQL和NoSQL架构设计与运维以及自动化平台的开发;目前在微博主要负责Feed核心系统相关业务的数据库运维和业务保障工作. 欢迎参与《Redis Cluster探索与思考》讨论,分享您的想法,编程之家PHP学院为您提供专业教程。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |