配色: 字号:
Redis 多机特性工作原理简介
2014-12-15 | 阅:  转:  |  分享 
  
Redis多机特性工作原理简介

黄健宏(huangz)

视频共分为三个部分,分别讲述Redis

的三个多机特性。

1.复制(replication)2.Sentinel

3.集群(cluster)

SLAVEOF、SYNC和PSYNC、一致性

复制

SLAVEOF命令的实现原理

复制

SLAVEOF

将一个服务器(从服务器)变成为另一个服务器

(主服务器)的复制品。











复制的执行步骤(4/5):同步

1.从服务器向主服务器发送SYNC命令。

2.主服务器调用BGSAVE,创建一个RDB文件,并使用缓冲区记录接下来

执行的所有写命令。

3.主服务器向从服务器发送RDB文件,从服务器接收并载入该文件。

4.主服务器将缓冲区储存的所有写命令发送给从服务器执行。

SYNC命令执行示例

但是……

执行SYNC命令之后,主从服务器的数据库状态

将达到一致状态(两个数据库都储存了相同的数

据),但这种一致性只是暂时性的,因为一旦主服

务器执行了新的写命令,主从服务器的数据库又

会变得不一致。

不一致性出现的例子

同步执行完毕之后



主服务器执行SETk6v6之后

主服务器从服务器

k1k1

k2k2

k3k3

k4k4

k5k5

k6N/A

主服务器和从服务器

k1

k2

k3

k4

k5

复制的执行步骤(5/5):命令传播

5.在主从服务器完成同步之后,主服务器每执行一个写命令,它都会将被执行的写命令发送给从服务器执行,这个操作被

称为“命令传播”(commandpropagate)。



注意!命令传播是一个持续的过

程:只要复制仍在继续,命

令传播就会一直进行,使得

主从服务器的状态可以一

直保持一致。

命令传播示例

执行并发送SETk6v6之后主服务器从服务器

k1k1

k2k2

k3k3

k4k4

k5k5

k6k6

SYNC和PSYNC的区别

复制

从Redis2.8开始,Redis使用PSYNC

命令代替SYNC命令。

PSYNC比起SYNC的最大改进在于PSYNC实现了部分同步(partialsync)特性:

在主从服务器断线并重连时,只要条件允许,

PSYNC可以让主服务器只向从服务器同步断线

期间缺失的数据,而不用重新向从服务器同步整

个数据库。



SYNC处理断线重连

从服务器在断线之前

已经拥有主服务器的

绝大部分数据,要让主

从服务器重新回到一

致状态,真正需要向从

服务器发送的是

k10087、k10088、

k10089这三个键的数

据。

SYNC命令的做法

——将主服务器的整

个数据库重新同步给

从服务器——是极度

浪费的!

PSYNC处理断线重连

PSYNC只会将

从服务器断线期

间缺失的数据发

送给从服务器。



两个例子的情况

是相同的,但

SYNC需要发送

包含整个数据库

的RDB文件,而

PSYNC只需要

发送三个命令。

结论

如果主从服务器所处的网络环境并不那么好的话

(经常断线),那么请尽量使用Redis2.8或以上

版本,这可以节约大量网络资源、计算资源、内存

资源——这些消耗都来自重复创建和传输RDB

文件。

一致性问题

复制

命令传播需要花费一段时间来完成

在主服务器执行完步骤(1)发送的命令之后、直

到从服务器执行完步骤(3)发送的命令之前的这

段时间里面,主从服务器状态并不一致。



现在,考虑这样一种情况……

客户端与主服务器的连接非常快,而主从服务器之间的连接却非常慢。

客户端向主服务器发送了命令SETn10086,并在获得返回OK之后,向从服务器发送GETn。

但是这时主服务器传播的SETn10086因为网络原因仍然未到达从服务器,那么客户端获得的键n的值将是错误的(过期的)。

结论

●Redis目前的复制实现只保证最终一致性,而不

是强一致性。

●如果程序不能够容忍过期数据,那么就不要读取

从服务器。

●未来:unstable分支中的WAIT命令——阻塞最

多N秒,直到客户端之前发送的命令已经被复制

到至少M个从服务器,实现同步复制效果。

http://antirez.com/news/66

构造、实例监视、下线判断、故障转移

Sentinel

Sentinel的构造

Sentinel是一个监视器,它可以根据被监视

实例的身份和状态来判断应该执行何种动

作。

DEFsentinel():

whilesentinel_is_running():

FORinstanceINall_instances:

instance.check_status()#检查实例的当前状态

IFinstance.role==MASTER:#实例是一个主服务器

IFinstance.status==FAIL:handle_master_down()

IFinstance.status==OK:...

IFinstance.role==SLAVE:#实例是一个从服务器



IFinstance.role==SENTINEL:#实例是一个Sentinel

...

被监视的实例可以是主服务器、从服务器、或者其他Sentinel。

监视主服务器

Sentinel通过用户给定的配置文件来发现主服务器。



############master1configure##############

sentinelmonitormaster1127.0.0.163792

sentineldown-after-millisecondsmaster130000

sentinelparallel-syncsmaster11

sentinelfailover-timeoutmaster1900000



############master2configure##############

sentinelmonitormaster2127.0.0.1123455

sentineldown-after-millisecondsmaster250000

sentinelparallel-syncsmaster25

sentinelfailover-timeoutmaster2450000



Sentinel会与被监视的主服务器创建两个网络连接:

命令连接用于向主服务器发送命令。

订阅连接用于订阅指定的频道,从而发现监视同一主服务器的其他Sentinel(细节稍后介绍)。

监视从服务器

Sentinel通过向主服务器发送INFO命令来自动获得所

有从服务器的地址。



redis>INFO

#othersection...

#Replication

role:master

...

slave0:ip=127.0.0.1,port=11111,state=online,offset=43,lag=0

slave1:ip=127.0.0.1,port=22222,state=online,offset=43,lag=0

slave2:ip=127.0.0.1,port=33333,state=online,offset=43,lag=0



#othersection...



跟主服务器一样,Sentinel会与每个被发现的从服务器创建命令连接和订阅连接。

发现其他Sentinel

Sentinel会通过命令连接向被监视的主从服务器发送HELLO

信息,以此来向其他Sentinel宣告自己的存在。

与此同时,Sentinel会通过订阅连接收听其他Sentinel的

HELLO信息,以此来发现监视同一个主服务器的其他

Sentinel。

例子:发现其他Sentinel

sentinel1通过发送HELLO信息来让sentinel2和sentinel3发现自己,其他两个sentinel也会进行类似的操作。

监视其他Sentienl

●Sentinel之间会互相创建

命令连接,用于进行通信。

●因为已经有主从服务器作

为发送和接收HELLO信

息的中介,所以Sentinel

之间不会创建订阅连接。

检测实例的状态

Sentinel使用PING命

令来检测实例的状态:

如果实例在指定的时间

内没有返回,或者返回

错误的回复,那么该实

例会被Sentinel判断

为下线。

下线状态(1/2)

从服务器和其他Sentinel的下线状态为PFAIL

(probablyfail):

●Sentinel不会与这个状态下的其他Sentinel

交换信息。

●这个状态的从服务器也不会在故障转移

(failover,细节稍后介绍)时被选为新的主服务

器。

下线状态(2/2)

主服务器的下线状态分为PFAIL和FAIL两级:

●PFAIL状态:当前Sentinel认为主服务器已下线。●FAIL状态:通过多个Sentinel互相通信,确认主服

务器已经下线。●换言之,对于主服务器来说,FAIL才是真正的下线

状态。●sentinelmonitor

示例:检测主服务器下线

监视同一个主服务

器的多个Sentinel

之间会互相交流信

息,如果总共有



Sentinel认为主服

务器已下线

(PFAIL),那么这

个主服务器将被

Sentienl判断为

FAIL状态。

一旦主服务器被判断为FAIL,Sentinel

就会对下线主服务器进行故障转移。

步骤:

1.在下线主服务器的所有从服务器中选出一个作为新的主服务

器,被选中的从服务器是所有从服务器中数据最新的。

2.Sentinel向被选中的从服务器发送SLAVEOFNOONE,

将它升级为主服务器。

3.向其他从服务器发送SLAVEOF

,让其他从服务器开始复制新的主服务

器。

故障转移示例

主服务器FAIL进行故障转移

节点、槽、命令执行、复制和故障转移

集群

集群的构成

一个集群由一个或多个节点(node)组成,其中

主节点(master)负责储存键值对,而从节点

(slave)则负责复制主节点。

每个节点互相连接。

一个包含三个主节点,三个从节点的集群。

分片(sharding)

●集群将整个数据库分为

16384(2的14次方)个

槽。

●每个主节点可以负责处理

0个至16384个槽。

●当16384个槽都有主节点

负责处理时,集群进入上

线状态。将16384个槽分别指派给7000、7001和7002这三个主节点。

槽的计算公式

集群使用公式CRC16(key)&16383计算键key

属于哪个槽。

在集群里面执行命令的两种情况

1.命令发送到了正确的节点(命令要处理的键所在的

槽正好是由接收命令的节点负责),那么该节点执行

命令,就像单机Redis服务器一样。

2.命令发送到了错误的节点(接收到命令的节点并非

处理键所在槽的节点),那么节点将向客户端返回一

个转向(redirection)错误,告知客户端应该到哪个

节点去执行这个命令,客户端会根据错误信息,重新

向正确的节点发送命令。

情况一:命令发送给正确的节点

键date位于2022槽,该槽由节点7000负责,

命令会直接执行。

7000:槽0~50007001:槽5001~10000

7002:槽10001~16383

情况二:命令发送给了错误的节点(1/2)

键date所在的槽2022并非由节点7001负责,7001返回转向错误。

7000:槽0~50007001:槽5001~10000

7002:槽10001~16383

转向错误格式:MOVED:

情况二:命令发送给了错误的节点(2/2)

客户端根据转向错误的指引,转向至节点7000,

并重新发送命令。

7000:槽0~50007001:槽5001~10000

7002:槽10001~16383

转向错误的实现(1/2)

集群中的节点会互相告知对方,自己负责处理哪些

槽。



转向错误的实现(2/2)

●集群中的每个节点都会记录16384

个槽分别由哪个节点负责,从而形成

一个“槽表”(slottable)。

●节点在接到命令时,会检查键所在的

槽是否由本节点处理,如果不是的

话,就根据槽号查找槽表,提取出正

确节点的地址信息,然后返回转向错

误。

集群节点的复制

集群的复制特性重用了SLAVEOF命令的代码,所

以集群节点的复制行为和SLAVEOF命令的复制行

为完全相同。

集群主节点的故障转移

●集群的下线检测和故障转移等功能的实现没有重用

Sentinel的代码,但它们的运作原理基本一样。

●和独立运行的Sentinel不同,集群对主从节点的下线

检测、以及对主节点的故障转移操作,都是由主节点

本身负责的,这也即是说,在集群模式里面,主节点兼

顾了Sentinel的功能。

●RedisSentinel和集群节点的Sentinel特性的模式不

同使得它们很难直接重用整个代码基,但将来共用一

些函数应该还是没有问题的。

通过www.huangz.me联系我

谢谢观看!:)

献花(0)
+1
(本文系icecity0079...首藏)