百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

Redis 集群解决方案分析

mhr18 2024-11-30 12:27 21 浏览 0 评论

调研比较三个解决方案

  1. Twemproxy Twitter 是C
  2. Redis ClusterRedis官方是C
  3. Codis 豌豆荚 否Go+C

Redis常见集群技术

长期以来,Redis本身仅支持单实例,内存一般最多8~20GB。这无法支撑大型线上业务系统的需求。而且也造成资源的利用率过低——毕竟现在服务器内存动辄100~200GB。

为解决单机承载能力不足的问题,各大互联网企业纷纷出手,“自助式”地实现了集群机制。在这些非官方集群解决方案中,物理上把数据“分片”(sharding)存储在多个Redis实例,一般情况下,每一“片”是一个Redis实例。

包括官方近期推出的Redis Cluster,Redis集群有三种实现机制,分别介绍如下,希望对大家选型有所帮助。

1.1 客户端分片

这种方案将分片工作放在业务程序端,程序代码根据预先设置的路由规则,直接对多个Redis实例进行分布式访问。这样的好处是,不依赖于第三方分布式中间件,实现方法和代码都自己掌控,可随时调整,不用担心踩到坑。

这实际上是一种静态分片技术。Redis实例的增减,都得手工调整分片程序。基于此分片机制的开源产品,现在仍不多见。

这种分片机制的性能比代理式更好(少了一个中间分发环节)。但缺点是升级麻烦,对研发人员的个人依赖性强——需要有较强的程序开发能力做后盾。如果主力程序员离职,可能新的负责人,会选择重写一遍。

所以,这种方式下,可运维性较差。出现故障,定位和解决都得研发和运维配合着解决,故障时间变长。

这种方案,难以进行标准化运维,不太适合中小公司(除非有足够的DevOPS)。

1.2 代理分片

这种方案,将分片工作交给专门的代理程序来做。代理程序接收到来自业务程序的数据请求,根据路由规则,将这些请求分发给正确的Redis 实例并返回给业务程序。

这种机制下,一般会选用第三方代理程序(而不是自己研发),因为后端有多个Redis实例,所以这类程序又称为分布式中间件。

这样的好处是,业务程序不用关心后端Redis实例,运维起来也方便。虽然会因此带来些性能损耗,但对于Redis这种内存读写型应用,相对而言是能容忍的。

这是我们推荐的集群实现方案。像基于该机制的开源产品Twemproxy,便是其中代表之一,应用非常广泛。

基本架构

Twemproxy

增加Proxy层,由Proxy实现一致性哈希算法(支持:KETAMA/取模/随机)

数据分片算法:

采用一致性哈希算法,以KET 为例:

Redis Cluster 官方实现

关键点

各节点维护Key->Server的映射关系

Client可以向任意节点发起请求,节点不会转发请求,只是重定向Client

如果在Client第一次请求和重定向请求之间,Cluster拓扑发生改变,则第二次重定向请求将被再次重定向,直到找到正确的Server为止

数据分片算法:

Key空间被划分为16384个区间,每个Master节点负责一部分区间。

Codis

客户端可以连接到任意的codis-proxy,就和连接原生的Redis Server

由Zookeeper维护数据路由表和 codis-proxy 节点的元信息

数据分片算法:

Key空间被划分为1024个区间, 对于每个key来说, 通过以下公式确定所属的 Slot Id : SlotId = crc32(key) % 1024

每一个 slot 都会有一个特定的 server group id 来表示这个 slot 的数据由哪个 server group 来提供

水平扩容

Twemproxy:

不支持运行时水平扩容,需要重启。

根据一致性哈希算法进行数据重新分片。

Redis Cluster:

支持通过运行时增加Master节点来水平扩容,提升存储容量,尽力降低命中率波动

存在节点A,需要迁出其中的部分Key区间。新增节点B,接收由节点A迁出的Key区间。

相应Key区间的请求首先还是会发送给A节点:如果请求为新建Key则直接重定向到B节点;如果请求不是新建Key且A节点存储有对应的Key则直接作出响应,否则重定向到B节点

同时Cluster会调用实用工具redis-trib向A节点发送MIGRATE命令,把迁移区间内的所有Key原子的迁移到B节点:同时锁住A、B节点=》在A节点删除Key=》在B节点新建Key=》解锁

运行时动态迁移大尺寸键值可能造成响应时延

Codis:

支持运行时水平扩容

底层基于Codis Server特殊实现原子的数据迁移指令

主从备份

主从备份是否必须

Twemproxy:

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

故障发生时,没有数据复制的故障节点的Key会全部丢失

Redis Cluster:

没有主从备份的节点一旦故障,将导致整个集群失败:无法写入/读取任何Key;无法进行数据重新分片。

Codis:

若出现故障,需要手动配置节点,进行故障转移。

如果没有进行故障转移,只故障节点负责的slots 会失败

3.2 主从备份方案

Twemproxy本身不支持出从备份,和Redis Cluster一样,需要引入Redis本身的主备复制功能。

可以设置1主1备或者1主多备

当Slave节点接入Cluster时,就会向配置的Master节点发送SYNC命令。断开重连时,也会再次发送SYNC命令

此后Master将启动后台存盘进程,同时收集所有接收到的用于修改数据集的命令,在后台进程执行完毕后,Master将传送整个数据库文件到Slave,以完成一次完全同步。而Slave服务器在接收到数据库文件数据之后将其存盘并加载到内存中。此后,Master继续将所有已经收集到的修改命令,和新的修改命令依次传送给Slaves,Slave将在本次执行这些数据修改命令,从而达到最终的数据同步。

Redis的数据复制是异步的,无论在Master端还是Slave端都不会阻塞。

Slave会周期性确认收到的备份数据

Twemproxy引入主备复制后的架构更新为:

开启主备复制后的Redis Cluster的架构更新为下图,Client可以向任意节点发起请求,无论是Master节点还是Slave节点。

故障检测与转移

Twemproxy

故障检测

Twemproxy本身通过三个配置项实现:

auto_eject_hosts: true
timeout: 400
server_failure_limit: 3

如果Server Pool开启了auto_eject_hosts,则当连续server_failure_limit次访问某Server,都超时timeout无响应,则标记该节点为故障。

故障转移

故障节点将从Hash环上直接取下,之前保存在该Server上的Key将丢失。

故障转移耗时评估

假设配置:timeout=400ms, server_failure_limit=2, 则故障转移需要耗时800ms。

Twemproxy借助其他工具

使用Twemproxy时可以引入Redis Sentinel来进行故障检测。引入Redis Sentinel后Twemproxy的架构更新为:

每个Sentinel节点可以监控一个或多个Master节点,及其所有Slave节点

启动Redis Sentinel

redis-sentinel /path/to/sentinel.conf,其中的配置文件是必须的,配置文件将会被用来存储运行时状态信息。在配置文件中只需要指明要监视的Master节点列表。

无须为运行的每个 Sentinel 分别设监听同一Master的其他 Sentinel 的地址, 因为 Sentinel 可以通过发布与订阅功能来自动发现正在监视相同主服务器的其他 Sentinel

不必手动列出主服务器属下的所有从服务器, 因为 Sentinel 可以通过询问主服务器来获得所有从服务器的信息。

故障检测

每个 Sentinel 以每秒钟一次的频率向它所知的主服务器、从服务器以及其他 Sentinel 实例发送一个 PING 命令。

如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 那么这个实例会被 Sentinel 标记为主观下线。

如果一个Master被标记为主观下线, 那么正在监视这个Master的所有 Sentinel 要以每秒一次的频率确认主服务器的确进入了主观下线状态。

如果一个主服务器被标记为主观下线, 并且有足够数量的 Sentinel (至少要达到配置文件指定的数量)在指定的时间范围内同意这一判断, 那么这个主服务器被标记为客观下线。

当没有足够数量的 Sentinel 同意主服务器已经下线, 主服务器的客观下线状态就会被移除。 当主服务器重新向 Sentinel 的 PING 命令返回有效回复时, 主服务器的主观下线状态就会被移除。

故障转移

Redis Sentinel进行故障转移的过程:

某Sentinel节点发现主服务器已经进入客观下线状态。

该Sentinel发起选举,试图当选故障转移主持节点

如果当选失败, 那么在设定的故障迁移超时时间的两倍之后, 重新尝试当选。 如果当选成功, 那么执行以下步骤。

选出一个Slave节点,并将它升级为Master节点

向被选中的从服务器发送 SLAVEOF NO ONE 命令,让它转变为Master节点

通过发布与订阅功能, 将更新后的配置传播给所有其他 Sentinel , 其他 Sentinel 对它们自己的配置进行更新。

向已下线主服务器的Slave节点发送 SLAVEOF 命令, 让它们去复制新的Master节点

Redis Sentinel选择新的Master节点进行故障转移之后,Twemproxy无法找到新的Master节点,此时需要引入第四方工具redis-twemproxy-agent(node.js),更新Twemproxy配置,并重启。

故障转移耗时评估

每个 Sentinel 以每秒钟发送一次PING,配置down-after-milliseconds=2s,则主观下线耗时3s

由主观下线升:数量的 Sentinel (至少要达到配置文件指定的数量)在指定的时间范围内同意这一判断1s

Sentinel当选故障转移主持节点:1s

选出一个Slave节点,并将它升级为Master节点,向被选中的从服务器发送 SLAVEOF NO ONE 命令,让它转变为Master节点:0.5s

通过发布与订阅功能, 将更新后的配置传播给所有其他 Sentinel , 其他 Sentinel 对它们自己的配置进行更新:1s

总计耗时:6.5s

Redis Cluster

4.3.1 故障检测

节点状态的维护:

节点的拓扑结构是一张完全图:对于N个节点的Cluster,每个节点都持有N-1个输入TCP连接和N-1个输出TCP连接。

节点信息的维护:每秒随机选择节点发送PING包(无论Cluster规模,PING包规模是常量);每个节点保证在NODE_TIMEOUT/2 时间内,对于每个节点都至少发送一个PING包或者收到一个PONG包.

在节点间相互交换的PING/PONG包中有两个字段用来发现故障节点:PFAIL(Possible Fail)和FAIL。

PFAIL状态:

当一个节点发现某一节点在长达NODE_TIMEOUT的时间内都无法访问时,将其标记为PFAIL状态。

任意节点都可以将其他节点标记为PFAIL状态,无论它是Master节点还是Slave节点。

FAIL状态:

当一个节点发现另一节点被自己标记为PFAIL状态,并且在(NODE_TIMEOUT * FAIL_REPORT_VALIDITY_MULT)的时间范围内,与其他节点交换的PING/PONG包中,大部分Master节点都把该节点标记为PFAIL或者FAIL状态,则把该节点标记为FAIL状态,并且进行广播。

4.3.2 故障转移

4.3.2.1 Slave选举的时机

当某一Slave节点发现它的Master节点处于FAIL状态时,可以发起一次Slave选举,试图将自己晋升为Master。一个Master节点的所有Slave节点都可以发起选举,但最终只有一个Slave节点会赢得选举。Slave发起选举的条件:

Slave的Master处于FAIL状态

该MASTER节点存储的Key数量>0

Slave与Master节点失去连接的时间小于阀值,以保证参与选举的Slave节点的数据的新鲜度

Cluster逻辑时钟

Config epoch:

每个Master节点启动时都会为自己创建并维护configEpoch字段,设置初始值为0。Master会在自己的PING/PONG包中广播自己的configEpoch字段。Redis Cluster尽力保持各个Master节点的configEpoch字段取值都不同。算法:

每当一个Master节点发现有别的Master节点的configEpoch字段与自己相同时

并且自己的Node ID比对方小(字母顺序)

则把自己的currentEpoch+1

Slave的PING/PONG包中也包含configEpoch字段,Slave的configEpoch字段取值是它的Master的configEpoch字段取值,由最后一次与Master交换PING/PONG包时取得。

Cluster epoch:

每一个节点启动的时候都会创建currentEpoch字段,无论是Master节点还是Slave节点,并设置初始值为0。每当一个节点收到来自其他节点的PING/PONG包时,若其他节点的currentEpoch字段大于当前节点的currentEpoch字段,则当前节点把自己的currentEpoch字段设置为该新观察到的currentEpoch值。

4.3.2.3 Slave选举的过程

Slave节点递增自己的currentEpoch字段

发送FAILOVER_AUTH_REQUEST数据包给每一个MASTER节点

若MASTER节点投票晋升该SLAVE节点,则回复FAILOVER_AUTH_ACK。某个MASTER节点投过票之后,在NODE_TIMEOUT * 2时间内不能再给同一MASTER的SLAVE选举投票。

若Slave在MAX((2*NODE_TIMEOUT),2)的时间内获得大多数MASTER节点的投票,则赢得选举

其间,所有currentEpoch小于选举发起时取值的MASTER投票都会被丢弃

若没有任何Slave赢得选举,选举可以在MAX(NODE_TIMEOUT * 4,4)的时间后重新举行

Master节点投票逻辑

请求选举的Slave的Master必须处于FAIL状态

Master节点维护lastVoteEpoch字段,每当MASTER给某个选举请求投票时,更新lastVoteEpoch字段为请求的currentEpoch值

currentEpoch<lastVoteEpoch的选举请求都不予投票

currentEpoch<MASTER currentEpoch字段的选举请求都不予投票

选举优先权

当Slave节点发现Master节点处于FAIL状态时,不会立刻试图进行选举,而是会延迟一段时间,延迟时常用以下公式进行计算:

DELAY = 500 milliseconds + random delay between 0 and 500 milliseconds + SLAVE_RANK * 1000 milliseconds

其中,SLAVE_RANK由Slave收到Master数据复制的更新程度来衡量。在发起选举之前,Slave之间交换各自获得Master数据复制的更新排名,最新更新的SLAVE_RANK = 0, 其次更新的SLAVE_RANK = 1,以此类推...

故障转移耗时评估

假设配置NODE_TIMEOUT=2s,FAIL_REPORT_VALIDITY_MULT=3s

标记Master为PFAIL状态耗时NODE_TIMEOUT=2s

升级PFAIL状态为FAIL状态,耗时:NODE_TIMEOUT * FAIL_REPORT_VALIDITY_MULT = 6s

选举前随机延时期望:1s

收集足够多Master投票:MAX((2*NODE_TIMEOUT),2)=4s

总计耗时约:13s

4.3.3 主备平衡功能

Redis Cluster能够自动的迁移Slave节点,从Slave节点有冗余的Master节点到完全没有Slave节点的Master节点。

具体算法:

首先定义Good Slave:对于某一节点来说,如果另一个Slave节点没有处于FAIL状态,则认为该Slave节点为Good Slave节点。

当有Slave节点发现有Master节点没有Good Slave时开始触发主备平衡迁移。

所有发现有主备平衡需求之后,拥有最多Good Slave节点的Master节点的所有Slave中,Node ID最小的Slave节点真正开始迁移。成为没有没有Good Slave Master新Master。

可以配置cluster-migration-barrier参数,控制主备平衡迁移的时候,迁出Master最少需要拥有的Good Slave数

4.4 Codis

支持故障检测并报警

codis-redis-group中的Slave节点无法自动提升为Master节点

由管理员通过Web界面/命令行来手动操作

5.功能限制

Twemproxy:

不支持多key操作

不支持MULTI/EXEC

不支持EVAL

Redis Cluster:

当Client连接到集群的主体部分时可能有少量的写丢失,当Client连接到集群的小部分时可能有显著的写丢失

复杂的多Key操作(Set求并/求交)不能跨节点操作,可以通过使用Hash Tag使相关Key强制哈希到同一Server,但是在数据重新分片期间,还是可能有时间不可用

不支持MULTI/EXEC

Redis 3.0 正式版时间:2015年2月上旬

Codis:

不支持命令:KEYS, MOVE, OBJECT, RENAME, RENAMENX, SORT, SCAN, BITOP,MSETNX, BLPOP, BRPOP, BRPOPLPUSH, PSUBSCRIBE,PUBLISH, PUNSUBSCRIBE, SUBSCRIBE, UNSUBSCRIBE, DISCARD, EXEC, MULTI, UNWATCH, WATCH, SCRIPT EXISTS, SCRIPT FLUSH, SCRIPT KILL, SCRIPT LOAD, AUTH, ECHO, SELECT, BGREWRITEAOF, BGSAVE, CLIENT KILL, CLIENT LIST, CONFIG GET, CONFIG SET, CONFIG RESETSTAT, DBSIZE, DEBUG OBJECT, DEBUG SEGFAULT, FLUSHALL, FLUSHDB, INFO, LASTSAVE, MONITOR, SAVE, SHUTDOWN, SLAVEOF, SLOWLOG, SYNC, TIME

性能

Twemproxy

通常操作Proxy与直接操作Redis实例性能一样

最坏情况下有20%的性能下降

Redis Cluster

1000个节点内拥有线性的伸缩性:通常情况下与直接操作Redis实例性能相同。

不支持多核心,但是可以多进程

Codis

相对于单Redis实例40%性能损失

支持多核

相关推荐

Spring Boot 分布式事务实现简单得超乎想象

环境:SpringBoot2.7.18+Atomikos4.x+MySQL5.71.简介关于什么是分布式事务,本文不做介绍。有需要了解的自行查找相关的资料。本篇文章将基于SpringBoot...

Qt编写可视化大屏电子看板系统15-曲线面积图

##一、前言曲线面积图其实就是在曲线图上增加了颜色填充,单纯的曲线可能就只有线条以及数据点,面积图则需要从坐标轴的左下角和右下角联合曲线形成完整的封闭区域路径,然后对这个路径进行颜色填充,为了更美观...

Doris大数据AI可视化管理工具SelectDB Studio重磅发布!

一、初识SelectDBStudioSelectDBStudio是专为ApacheDoris湖仓一体典型场景实战及其兼容数据库量身打造的GUI工具,简化数据开发与管理。二、Select...

RAD Studio 、Delphi或C++Builder设计代码编译上线缩短开发时间

#春日生活打卡季#本月,Embarcadero宣布RADStudio12.3Athens以及Delphi12.3和C++Builder12.3,提供下载。RADStudio12.3A...

Mybatis Plus框架学习指南-第三节内容

自动填充字段基本概念MyBatis-Plus提供了一个便捷的自动填充功能,用于在插入或更新数据时自动填充某些字段,如创建时间、更新时间等。原理自动填充功能通过实现com.baomidou.myba...

「数据库」Sysbench 数据库压力测试工具

sysbench是一个开源的、模块化的、跨平台的多线程性能测试工具,可以用来进行CPU、内存、磁盘I/O、线程、数据库的性能测试。目前支持的数据库有MySQL、Oracle和PostgreSQL。以...

如何选择适合公司的ERP(选erp系统的经验之谈)

很多中小公司想搞ERP,但不得要领。上ERP的目的都是歪的,如提高效率,减少人员,堵住财务漏洞等等。真正用ERP的目的是借机提升企业管理能力,找出管理上的问题并解决,使企业管理更规范以及标准化。上ER...

Manus放开注册,但Flowith才是Agent领域真正的yyds

大家好,我是运营黑客。前天,AIAgent领域的当红炸子鸡—Manus宣布全面放开注册,终于,不需要邀请码就能体验了。于是,赶紧找了个小号去确认一下。然后,额……就被墙在了外面。官方解释:中文版...

歌浓酒庄总酿酒师:我们有最好的葡萄园和最棒的酿酒师

中新网1月23日电1月18日,张裕董事长周洪江及总经理孙健一行在澳大利亚阿德莱德,完成了歌浓酒庄股权交割签约仪式,这也意味着张裕全球布局基本成型。歌浓:澳大利亚年度最佳酒庄据悉,此次张裕收购的...

软件测试进阶之自动化测试——python+appium实例

扼要:1、了解python+appium进行APP的自动化测试实例;2、能根据实例进行实训操作;本课程主要讲述用python+appium对APP进行UI自动化测试的例子。appium支持Androi...

为什么说Python是最伟大的语言?看图就知道了

来源:麦叔编程作者:麦叔测试一下你的分析能力,直接上图,自己判断一下为什么Python是最好的语言?1.有图有真相Java之父-JamesGoshlingC++之父-BjarneStrou...

如何在Eclipse中配置Python开发环境?

Eclipse是著名的跨平台集成开发环境(IDE),最初主要用来Java语言开发。但是我们通过安装不同的插件Eclipse可以支持不同的计算机语言。比如说,我们可以通过安装PyDev插件,使Eclip...

联合国岗位上新啦(联合国的岗位)

联合国人权事务高级专员办事处PostingTitleIntern-HumanRightsDutyStationBANGKOKDeadlineOct7,2025CategoryandL...

一周安全漫谈丨工信部:拟定超1亿条一般数据泄露属后果严重情节

工信部:拟定超1亿条一般数据泄露属后果严重情节11月23日,工信部官网公布《工业和信息化领域数据安全行政处罚裁量指引(试行)(征求意见稿)》。《裁量指引》征求意见稿明确了行政处罚由违法行为发生地管辖、...

oracle列转行以及C#执行语句时报错问题

oracle列转行的关键字:UNPIVOT,经常查到的怎么样转一列,多列怎么转呢,直接上代码(sshwomeyourcode):SELECTsee_no,diag_no,diag_code,...

取消回复欢迎 发表评论: