Redis分布式集群几点说道

Redis数据量日益增大,使用的公司愈来愈多,不只用于作缓存,同时趋向于存储这一块,这样必促使集群的发展,各个公司也在收集适合本身的集群方案,目前行业用的比较多的是下面几种集群架构,大部分都是采用分片技术,保证单实例内存增大带来的一系列问题,下面所列出的codis方案目前正在不断测试过程当中,测试过程没有展现出来,主要从如下几点出发。node

 

测试架构和性能web

  一、keepalived+haproxy故障测试redis

  二、Zookeeper集群节点测试算法

  三、Codis-proxy集群节点测试数据库

  四、Codis-server集群节点测试浏览器

  五、脚本写入大量测试数据并模拟数据迁移缓存

  六、性能测试安全

 

下面具体介绍codis和其余几大集群方案ruby

集群方案:网络

  一、 主从高可用(该方案就是单实例形式,只是为了保证数据的安全,对于用户数据少,业务的前期能够采用,目前我司缓存架构就是采用该方案)

  二、 客户端分片(典型表明:Jedis。自主写分片算法,代码掌握在本身手中,可控性强,可是须要专业的开发运维人员维护,技术要求和维护成本高)

  三、代理分片(典型表明:Twemproxy,redis集群没有正式推出以前官网推荐的方案,也是目前使用最多的)

  四、 Redis cluster(3版本推出的集群方案,历时四年之多的开发)

  五、 Codis集群(豌豆荚15年开源的解决方案,开源以前其已经用了2年之多,与其同期官网推出redis cluster)

  六、 各大互联网公司自主研发的集群架构,可是尚未开源,可能也不会开源

 

根据以上的简单介绍,下面主要解释后面三种集群方案的特色,以及针对业务的具体状况,斟酌选择合适的架构思考。

codis架构图

 

 

简单说明:一、codis-proxy提供链接集群redis的服务入口

              二、codis-config管理工具,支持包括添加/删除redis/proxy节点,发起数据迁移等操做,自带一个dashboard工具,浏览器能够直观查看集群的运行状态

              三、codis-server-group实现redis读写的水平扩展、高性能

              四、codis-server实现redis实例服务,经过codis-ha实现服务的高可用

              五、Zookeeper/etcd存放数据路由表和codis-proxy节点的元信息,codis-config发起的命令经过其同步到各个存活的codis-proxy,则zookeeper若是出问题则可能致使数据不一致的状况或者严重的会对外提供服务形成影响

说明:一切知识点来源于官方,本人通过测试一步步验证,大体总结以上几点

 

Twemproxy架构图

 

 

简单说明:一、proxy提供分片算法和redis服务入口,支持高可用

              二、Redis提供实现实例,而且经过sentinel支持高可用

              三、Redis-Twemporxy提供通知底层HA切换至proxy

              四、每一个层结构出现问题或者变动节点信息等全部操做都须要从新规划分片算法,则须要重启服务

 

Redis cluster架构图

 

 

简单说明:一、redis cluster自己集群方案,客户端能够任一链接一个节点

            二、redis-trib.rb脚本为集群的管理工具,好比自动添加节点,规划槽位,迁移数据等一系列操做(ruby语言)

             三、每一个节点都和N-1个节点通讯,因此要维护好这个集群架构的每一个节点信息,否则会致使整个集群不可工做

             注意:如下三大方案redis cluster基于3.0版本

 

Redis集群方案各参数比较

 

Twemproxy

Codis

Redis Cluster

架构设计

分布式CAP,牺牲P性能,而仅仅只是数据分片

分布式CAP,牺牲P性能,设计初衷为数据一致性

分布式CAP,牺牲C数据强一致性原则,追求redis最大的特色性能

设计模型

Proxy-based

Proxy-based

Gossip/P2P

设计思路

分布式逻辑和存储引擎分开,逻辑层proxy代理,存储用的是原子redis,当每一个层面须要添加删除节点必须重启服务生效(要从新利用散列函数生成KEY分片更新)

分布式逻辑和存储引擎分开,逻辑层codis-proxy,存储用的是修改过的codis-server,这种好处是proxy层能够自动扩展和收缩,存储层也一样能够,每一个层面均可以热插拨

分布式的逻辑和存储引擎不分开,即又负责读写操做,又负责集群交互,升级困难,若是代码有bug,集群没法工做

架构特色

Proxy无状态,redis数据层有状态的,客户端能够请求任一proxy代理上面,再由其转发至正确的redis节点,该KEY分片算法至某个节点都是预先已经算好的,在proxy配置文件保存着,可是若是更新或者删除节点,又要根据一致性hash从新计算分片,而且重启服务

Proxy无状态,codis-server分为组间,每一个组存在一个主节点(必须有而且只能有一个)和多个从节点。客户端请求都是和proxy连接,连接哪一个proxy都同样,而后由它根据zookeeper路由信息转发至正确节点,直接能够定位到正确节点上

这个结构为无中心的组织,很差把控集群当前的存活状态,客户端能够向任一节点发送请求,再有其重定向正确的节点上。若是在第一次请求和重定向期间cluster拓扑结构改变,则须要再一次或者屡次重定向至正确的节点,可是这方面性能能够忽悠不计

codis独特之处

不支持

一、 有中心节点,逻辑问题交由proxy处理,codis还有个特色下层存储能够根据数据的冷热程度把冷数据暂时保存至磁盘,待其为热数据的时候又能够上线(这点我尚未测试)

二、 提供数据在线迁移的工具

好比需求要从redis或者twemproxy迁移数据至codis或者之后redis数据库中,又不想直接预热,能够借助其提供的redis-port命令行工具

不支持

开发语言

C语言

Go语言、C语言

C语言

服务启动方式

单进程

多进程

单进程

性能问题

一、 单点的话比起原子redis下降20%左右;

二、 增长PIPELINE管道提升性能

只要是代理的设计性能瓶颈确定在其,因redis实在太快

一、 至关于单redis实例40%性能丢失(从最开始的版本比Twemproxy慢20%至目前比其快100%);

二、 弥补:增长proxy数量和支持多核,比起Twemproxy仍是好一点,因Twemproxy最好的状况跑满一个CPU;

三、 弥补:增长PIPELINE管道提升性能

只要是代理的设计性能瓶颈确定在其,因redis实在太快

没什么损失,追求的就是这个

1000个节点内拥有线性的伸缩性,和操做redis实例性能差很少

分片算法

Redis一致hash,当初设计好如后续变动修改(增减节点)须要配置proxy通知新的算法,重启服务

 

经过presharding采用solt槽位的形式,整个集群分为1024个哈希槽,分片算法位SlotId = crc32(key) % 1024,增减节点不须要重启服务

采用solt槽位的形式,整个集群分为16384个哈希槽,分片算法位SlotId = crc16(key) % 16384,增减节点不须要重启服务

所需组件

Redis、twemproxy(nutcracker)

Codis、zookeeper

redis

数据一致性

不能保证强一致性

一、 如redis cluster第一种状况没有,设计不同

二、 网络分裂,这种状况其有监控工具能够通知管理员某个主节点宕机,这时若是管理员切换HA(可是不提供自动提高从节点为主节点,因从节点变为主节点必须更新分片算法,重启服务),数据就会丢失,因主节点的写命令会丢失,除非再次AOF同步最后一条写命令,两者如国管理员能够判断其为网络分裂,等待网络恢复是主节点会向从节点同步写命令数据

强一致性

一、 数据迁移过程当中数据强一致性性,因迁移都是一个个KEY原子迁移,每次操做都是给ZK发送信息,通知proxy,同时全部操做都是上一把锁,假如该期间有客户端访问,则提高访问该KEY的操做为优先操做,快速迁移至新节点,访问转移至新节点,不会访问老的KEY,如期间也能够中断正在同步的数据,也是不影响,由于redis没有回滚机制,要么成功要么失败

二、 网络分裂:由于它的设计初衷就是不考虑HA自动切换(后面添加该功能),等到网络恢复Zookeeper保证数据一致性,写命令不会丢失,全部操做都要在zookeeper上面注册

不能保证强一致性

好比官网给出的两种有可能丢失写命令的状况以下

一、 客户端向主节点A发送一条写命令,主节点是首先立马向客户端返回命令回复,而后再把刚刚的执行写命令同步至从节点,追求性能所致该设计

二、 网络分裂(network partition),若是时间很长致使A节点的从节点转换为主节点,然这中间可能存在客户端正在和A节点通讯也就被孤立了,这样写的命令将丢失,如当网络恢复A又从新加入集群

数据的特殊安全

一、 好比某段时间业务数据一下爆表(内存写满),数据来不及迁移,这样的话redis会根据LRU策略,会淘汰一部分老的key,这个没办法,因此运维中当内存使用80%时应该扩容

二、 主从切换过程当中有一部分数据丢失(主挂了到从切换上来丢失的这部分数据)

磁盘IO

基于redis自己的持久化(RDB和AOF),确定会存在数据丢失的状况

数据的迁移

不可在线迁移,而且迁移完以后须要修改配置文件的分片算法,再从新启动Twemproxy服务,从新识别分片算法

采用sharding在线迁移数据,安全透明,能够自动平衡数据到其余节点,至关于可热插拨,不会形成响应时延(因迁移时会另外有个进程来作,数据迁移仍是原子的数据迁移指令,这样迁移的话就会至关慢一些)

在线迁移数据,动态迁移KEY值会形成响应时延(迁移数据是拷贝RDB数据文件,并且由于redis是单进程的),另外新节点solt又不自动,依赖ruby(redis cluster集群管理和分配脚本)脚原本平衡数据,无中心设计如此

水平扩容缩容(增减节点)

Redis存储层操做,不提供自动的解决方案,而且要本身写脚本支持数据的搬迁活动,而后更改proxy哈希算法,重启服务

Redis存储层,都是在线操做(扩容数据迁移,缩容的话先搬迁数据至别的节点,而后下线该节点)

没有代理和存储之分,能够在线操做(扩容数据迁移,缩容的话先搬迁数据至别的节点,而后下线该节点)

主从是否必须

一、 没有数据复制不影响可用节点代替故障节点

二、 若是没有作备份,故障节点key所有丢失

一、 故障节点若是没有备份,则丢失掉该组的全部数据,可是不影响其余组的运行,不会致使整个集群坏掉

二、 若有备份节点,则把其升为主节点,集群没有影响,正常运转(须要管理员手动变动从节点为主节点,最新版本添加HA功能)

没有主从复制的节点一旦故障,将致使整个集群不可用,没法写入或者读入任何key,没法进行数据从新分片

官网建议:至少3主3从

主从特色

基于redis自己的主从方案(利用发布/订阅机制,采用广播形式),

采用异步复制(asynchronous replication)的方案,不管是master端仍是slave端都不会引发阻塞,可是确定是存在数据丢失的状况

集群设计

一、 proxy部署高可用(多proxy结合keepalived+haporxy)

二、 redis层设计多主多从部署

一、 proxy部署(多proxy+zookeeper集群方案,而且结合keepalived+haporxy)

二、 codis-server部署多组,每组部署一主多从架构

利用redis自己部署集群:至少3主3从

HA方案

Proxy层已经有了,由上面的设计,redis层基于自带的HA解决方案(sentinel),这里不阐述sentinel机制

Proxy层已经有了,存储层原本设计就没有考虑自动HA切换,后面根据用户强烈的要求,目前添加codis-ha解决

自主监控自动切换(把sentinel功能搬迁过来)

故障监控

自带监控并告警

自带监控并告警

目前尚未提供

故障检测和故障转移时间

一、proxy配置文件设置:auto_eject_hosts: true  

timeout: 400  

server_failure_limit: 3

当proxy server超时400毫且3次重试机会,则认为该proxy节点坏掉,这样故障节点从hash环直接取下,而且清理该Key信息

故障转移耗时:400*3=1200毫秒

二、若是存储层加入sentinel作HA

(注意:底层redis转移故障以后,因proxy层不知道该配置信息已经变更,此时须要引入第四方工具redis-twemproxy-agent(node.js),更新Twemproxy配置,并重启)

故障转移耗时:

每一个sentinel以每秒发送一次ping,配置down-after-milliseconds=2s,则主观认为下线3秒,然数量sentinel(配置文件能够配置)承认赞成须要1s,再sentinel当选故障转移主持节点须要1秒,选出slave升级为master须要0.5秒,经过发布和订阅推送更新配置至其余sentinel而且配置更新须要1秒,这样总共耗时6.5秒。

一、 proxy层配置文件:

backend_ping_period=5 则表示5秒zookeeper没有等到pong回应就认为proxy已经坏掉

故障转移耗时:5秒

二、 存储层原本不设置自动故障迁移的

(后面添加codis-ha机制)

过程:codis-ha经过dashboard监控每组的存活情况,zookeeper可以快速知道存活的proxy节点,而后休眠3秒再次监控至重试3次,大体10秒左右时间切换,可是官方建议,仍是不但愿使用该解决方案,因主节点有问题,立马切换从节点为主节点可能致使数据丢失的状况。推荐你们使用手动切换,作好监控,肯定好数据安全而后使用web界面或者命令手动操做(因用户的强烈要求才加入该解决方案)

Redis cluster拓扑结构是一张彻底图:每一个节点都持有N-1个输入TCP和N-1个输出TCP。

这里不阐述故障监控和切换的流程(好比FAIL状态、slave选主时机和cluster逻辑时钟等)

故障转移耗时(配置文件能够修改)

Node_time=2

Fail_report_validity_mult=3

标记master为pfail耗时2秒,升级pfail为fail状态耗时为2*3=6秒,选主前随机延期指望为1秒,收集足够多master投票为max((2*node_time),2)=4秒

这样总共耗时13秒。

 

功能限制

一、 不支持多key操做

二、 不支持MULTI/EXEC

三、 不支持EVAL

比较多,能够查看官方文档

一、 复杂的多KEY(set求并求交集)不能跨节点操做

二、 不支持MULTI/EXEC

三、 写丢失比较频繁

提供支持

不在维护

目前活跃状态

官网主打

客户端driver工具

保持不变(redis支持的都支持)

保持不变(redis支持的都支持)

只能支持cluster协议的客户端工具(目前官网上面说的是针对JAVA的是Jides,针对PHP的是Predis,并且不成熟)

归纳

一、 轻量级

二、 在proxy层实现一致性哈希

三、 快速的故障转移

四、 可借助sentinel实现底层HA

五、 每次变动必须重启生效

一、 基于zookeeper的proxy高可用,zookeeper会记录整个集群的生存状态,则须要维护好zookeeper

二、 优点为动态水平扩容,平衡数据,在迁移的时候不影响业务访问和响应时间,这点很炫,也是它主打的方向

三、 Dashboard操做下降人失误率,图形直观查看信息

四、 强一致数据(也是设计的重点)

一、 性能好(也是设计的原则)

二、 无中心组织结构,有利有弊

三、 故障转移响应时间长

四、 有写丢失,比较频繁

相关文章
相关标签/搜索