什么叫系统不可用:

什么是99.99高可用性:

高可用计算规则,全年 系统可用的时间 / 全年

redis不可用是什么?

redis主从基于哨兵模式的高可用:

哨兵的主要功能:

(1)集群监控,负责监控redis master和slave进程是否正常正常工作

(2)消息通知,如果某个redis实例有故障,那么哨兵负责发送消息作为报警通知给管理员

(3)故障迁移,如果master node挂掉了,会自动转移到slave node 上

(4) 配置中心,如果故障发生了,通知client客户端新的master地址

哨兵的核心知识:

(1) 哨兵至少需要 3 个实例,保证自己的健壮性

(2) 哨兵 + redis,是不会保证数据零丢失的,只能保证redis集群的高可用

(3) 哨兵 + redis ,这种复制的架构,尽量多做容灾演练

为什么哨兵最少要三台?:

2台的 majority = 2, (reids 服务器发生问题之后,需要两台都同意,才能执行迁移操作)

3 台的 majority = 2, (两台哨兵同意即可)

4 台的 majority = 2, (两台哨兵同意即可))

5 台的 majority = 3 (三台哨兵同意即可))

如果哨兵只有两天,呢么其中一台发生问题,即时检查到了redis master发生问题,也不能执行redis迁移(必须要两台都同意迁移,才可以迁移)

redis哨兵主备切换的数据丢失问题:

1)异步复制:

2) 集群脑裂

解决异步复制和脑裂导致的数据丢失(redis.conf文件中配置):

min-slaves-to-write 1

min-slaves-max-lag 10

要求至少有一个slave,复制和同步数据的延迟不能超过10秒

如果说一旦所有的slave,数据复制和同步延迟都超过了10秒,这时候master将不会接收任何写请求

redis哨兵核心底层原理:

1.sdown 和 odown

sdown和odown两种失败状态

sdown是主观宕机,就一个哨兵如果自己觉得一个master宕机了,那么就是主观宕机

odown是客观宕机,如果quorum数量的哨兵都觉得一个master宕机了,那么就是客观宕机

sdown达成的条件很简单,如果一个哨兵ping一个master,超过了is-master-down-after-milliseconds指定的毫秒数之后,就主观认为master宕机

sdown到odown转换的条件很简单,如果一个哨兵在指定时间内,收到了quorum指定数量的其他哨兵也认为那个master是sdown了,那么就认为是odown了,客观认为master宕机

2.哨兵集群的自动发现机制

哨兵互相之间的发现,是通过redis的pub/sub系统实现的,每个哨兵都会往__sentinel__:hello这个channel里发送一个消息,这时候所有其他哨兵都可以消费到这个消息,并感知到其他的哨兵的存在

每隔两秒钟,每个哨兵都会往自己监控的某个master+slaves对应的__sentinel__:hello channel里发送一个消息,内容是自己的host、ip和runid还有对这个master的监控配置

每个哨兵也会去监听自己监控的每个master+slaves对应的__sentinel__:hello channel,然后去感知到同样在监听这个master+slaves的其他哨兵的存在

每个哨兵还会跟其他哨兵交换对master的监控配置,互相进行监控配置的同步

3.slave配置的自动纠正

哨兵会负责自动纠正slave的一些配置,比如slave如果要成为潜在的master候选人,哨兵会确保slave在复制现有master的数据; 如果slave连接到了一个错误的master上,比如故障转移之后,那么哨兵会确保它们连接到正确的master上

哨兵会自动更改redis的配置文件

4.slave->master选举算法

如果一个master被认为odown了,而且majority哨兵都允许了主备切换,那么某个哨兵就会执行主备切换操作,此时首先要选举一个slave来

会考虑slave的一些信息

(1)跟master断开连接的时长

(2)slave优先级

(3)复制offset

(4)run id

如果一个slave跟master断开连接已经超过了down-after-milliseconds的10倍,外加master宕机的时长,那么slave就被认为不适合选举为master

(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state

接下来会对slave进行排序:

(1)按照slave优先级进行排序,slave priority越低,优先级就越高

(2)如果slave priority相同,那么看replica offset,哪个slave复制了越多的数据,offset越靠后,优先级就越高

(3)如果上面两个条件都相同,那么选择一个run id比较小的那个slave

5.quorum和majority

每次一个哨兵要做主备切换,首先需要quorum数量的哨兵认为odown,然后选举出一个哨兵来做切换,这个哨兵还得得到majority哨兵的授权,才能正式执行切换

如果quorum < majority,比如5个哨兵,majority就是3,quorum设置为2,那么就3个哨兵授权就可以执行切换

但是如果quorum >= majority,那么必须quorum数量的哨兵都授权,比如5个哨兵,quorum是5,那么必须5个哨兵都同意授权,才能执行切换

6.configuration epoch

哨兵会对一套redis master+slave进行监控,有相应的监控的配置

执行切换的那个哨兵,会从要切换到的新master(salve->master)那里得到一个configuration epoch,这就是一个version号,每次切换的version号都必须是唯一的

如果第一个选举出的哨兵切换失败了,那么其他哨兵,会等待failover-timeout时间,然后接替继续执行切换,此时会重新获取一个新的configuration epoch,作为新的version号

7.configuraiton传播

哨兵完成切换之后,会在自己本地更新生成最新的master配置,然后同步给其他的哨兵,就是通过之前说的pub/sub消息机制

这里之前的version号就很重要了,因为各种消息都是通过一个channel去发布和监听的,所以一个哨兵完成一次新的切换之后,新的master配置是跟着新的version号的

其他的哨兵都是根据版本号的大小来更新自己的master配置的

配置哨兵模式(主从状态监控)

1. Redis Sentinel搭建

1.1. Redis Sentinel的部署须知

1. 一个稳健的Redis Sentinel集群,应该使用至少 三个Sentinel实例,并且保证讲这些实例放到 不同的机器 上,甚至不同的 物理区域。

2. Sentinel无法保证 强一致性。

3. 常见的 客户端应用库 都支持Sentinel。

4. Sentinel需要通过不断的 测试 和 观察,才能保证高可用。

1.2. Redis Sentinel的配置文件# 哨兵sentinel实例运行的端口,默认26379

port 26379

# 哨兵sentinel的工作目录

dir ./

# 哨兵sentinel监控的redis主节点的

## ip:主机ip地址

## port:哨兵端口号

## master-name:可以自己命名的主节点名字(只能由字母A-z、数字0-9 、这三个字符".-_"组成。)

## quorum:当这些quorum个数sentinel哨兵认为master主节点失联 那么这时 客观上认为主节点失联了

# sentinel monitor

sentinel monitor mymaster 127.0.0.1 6379 2

# 当在Redis实例中开启了requirepass ,所有连接Redis实例的客户端都要提供密码。

# sentinel auth-pass

sentinel auth-pass mymaster 123456

# 指定主节点应答哨兵sentinel的最大时间间隔,超过这个时间,哨兵主观上认为主节点下线,默认30秒

# sentinel down-after-milliseconds

sentinel down-after-milliseconds mymaster 30000

# 指定了在发生failover主备切换时,最多可以有多少个slave同时对新的master进行同步。这个数字越小,完成failover所需的时间就越长;反之,但是如果这个数字越大,就意味着越多的slave因为replication而不可用。可以通过将这个值设为1,来保证每次只有一个slave,处于不能处理命令请求的状态。

# sentinel parallel-syncs

sentinel parallel-syncs mymaster 1

# 故障转移的超时时间failover-timeout,默认三分钟,可以用在以下这些方面:

## 1. 同一个sentinel对同一个master两次failover之间的间隔时间。

## 2. 当一个slave从一个错误的master那里同步数据时开始,直到slave被纠正为从正确的master那里同步数据时结束。

## 3. 当想要取消一个正在进行的failover时所需要的时间。

## 4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来同步数据了

# sentinel failover-timeout

sentinel failover-timeout mymaster 180000

# 当sentinel有任何警告级别的事件发生时(比如说redis实例的主观失效和客观失效等等),将会去调用这个脚本。一个脚本的最大执行时间为60s,如果超过这个时间,脚本将会被一个SIGKILL信号终止,之后重新执行。

# 对于脚本的运行结果有以下规则:

## 1. 若脚本执行后返回1,那么该脚本稍后将会被再次执行,重复次数目前默认为10。

## 2. 若脚本执行后返回2,或者比2更高的一个返回值,脚本将不会重复执行。

## 3. 如果脚本在执行过程中由于收到系统中断信号被终止了,则同返回值为1时的行为相同。

# sentinel notification-script

sentinel notification-script mymaster /var/redis/notify.sh

# 这个脚本应该是通用的,能被多次调用,不是针对性的。

# sentinel client-reconfig-script

sentinel client-reconfig-script mymaster /var/redis/reconfig.sh

1.3. Redis Sentinel的节点规划角色IP地址端口号

Redis Master10.206.20.23116379

Redis Slave110.206.20.23126379

Redis Slave210.206.20.23136379

Redis Sentinel110.206.20.23116380

Redis Sentinel210.206.20.23126380

Redis Sentinel310.206.20.23136380

1.4. Redis Sentinel的配置搭建

搭建reids-server 集群:

1.4.1. Redis-Server的配置管理

分别拷贝三份redis.conf文件到/usr/local/redis-sentinel目录下面。三个配置文件分别对应master、slave1和slave2三个Redis节点的启动配置。

$ sudo cp /usr/local/redis-4.0.11/redis.conf /usr/local/redis-sentinel/redis-16379.conf

$ sudo cp /usr/local/redis-4.0.11/redis.conf /usr/local/redis-sentinel/redis-26379.conf

$ sudo cp /usr/local/redis-4.0.11/redis.conf /usr/local/redis-sentinel/redis-36379.conf

分别修改三份配置文件如下:

主节点:redis-16379.confdaemonize yes

pidfile /var/run/redis-16379.pid

logfile /var/log/redis/redis-16379.log

port 16379

bind 0.0.0.0

timeout 300

databases 16

dbfilename dump-16379.db

dir ./redis-workdir

masterauth 123456

requirepass 123456

从节点1:redis-26379.confdaemonize yes

pidfile /var/run/redis-26379.pid

logfile /var/log/redis/redis-26379.log

port 26379

bind 0.0.0.0

timeout 300

databases 16

dbfilename dump-26379.db

dir ./redis-workdir

masterauth 123456

requirepass 123456

slaveof 127.0.0.1 16379

从节点2:redis-36379.confdaemonize yes

pidfile /var/run/redis-36379.pid

logfile /var/log/redis/redis-36379.log

port 36379

bind 0.0.0.0

timeout 300

databases 16

dbfilename dump-36379.db

dir ./redis-workdir

masterauth 123456

requirepass 123456

slaveof 127.0.0.1 16379

如果要做自动故障转移,建议所有的redis.conf都设置masterauth。因为自动故障只会重写主从关系,即slaveof,不会自动写入masterauth。如果Redis原本没有设置密码,则可以忽略。

1.4.2. Redis-Server启动验证

按顺序分别启动16379,26379和36379三个Redis节点,启动命令和启动日志如下:

Redis的启动命令:

$ sudo redis-server /usr/local/redis-sentinel/redis-16379.conf

$ sudo redis-server /usr/local/redis-sentinel/redis-26379.conf

$ sudo redis-server /usr/local/redis-sentinel/redis-36379.conf

查看Redis的启动进程:

$ ps -ef | grep redis-server

0  7127     1   0  2:16下午 ??         0:01.84 redis-server 0.0.0.0:16379

0  7133     1   0  2:16下午 ??         0:01.73 redis-server 0.0.0.0:26379

0  7137     1   0  2:16下午 ??         0:01.70 redis-server 0.0.0.0:36379

查看Redis的启动日志:

节点redis-16379$ cat /var/log/redis/redis-16379.log

7126:C 22 Aug 14:16:38.907 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo

7126:C 22 Aug 14:16:38.908 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=7126, just started

7126:C 22 Aug 14:16:38.908 # Configuration loaded

7127:M 22 Aug 14:16:38.910 * Increased maximum number of open files to 10032 (it was originally set to 256).

7127:M 22 Aug 14:16:38.912 * Running mode=standalone, port=16379.

7127:M 22 Aug 14:16:38.913 # Server initialized

7127:M 22 Aug 14:16:38.913 * Ready to accept connections

7127:M 22 Aug 14:16:48.416 * Slave 127.0.0.1:26379 asks for synchronization

7127:M 22 Aug 14:16:48.416 * Full resync requested by slave 127.0.0.1:26379

7127:M 22 Aug 14:16:48.416 * Starting BGSAVE for SYNC with target: disk

7127:M 22 Aug 14:16:48.416 * Background saving started by pid 7134

7134:C 22 Aug 14:16:48.433 * DB saved on disk

7127:M 22 Aug 14:16:48.487 * Background saving terminated with success

7127:M 22 Aug 14:16:48.494 * Synchronization with slave 127.0.0.1:26379 succeeded

7127:M 22 Aug 14:16:51.848 * Slave 127.0.0.1:36379 asks for synchronization

7127:M 22 Aug 14:16:51.849 * Full resync requested by slave 127.0.0.1:36379

7127:M 22 Aug 14:16:51.849 * Starting BGSAVE for SYNC with target: disk

7127:M 22 Aug 14:16:51.850 * Background saving started by pid 7138

7138:C 22 Aug 14:16:51.862 * DB saved on disk

7127:M 22 Aug 14:16:51.919 * Background saving terminated with success

7127:M 22 Aug 14:16:51.923 * Synchronization with slave 127.0.0.1:36379 succeeded

以下两行日志日志表明,redis-16379作为Redis的主节点,redis-26379和redis-36379作为从节点,从主节点同步数据。

7127:M 22 Aug 14:16:48.416 * Slave 127.0.0.1:26379 asks for synchronization

7127:M 22 Aug 14:16:51.848 * Slave 127.0.0.1:36379 asks for synchronization

节点redis-26379$ cat /var/log/redis/redis-26379.log

7132:C 22 Aug 14:16:48.407 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo

7132:C 22 Aug 14:16:48.408 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=7132, just started

7132:C 22 Aug 14:16:48.408 # Configuration loaded

7133:S 22 Aug 14:16:48.410 * Increased maximum number of open files to 10032 (it was originally set to 256).

7133:S 22 Aug 14:16:48.412 * Running mode=standalone, port=26379.

7133:S 22 Aug 14:16:48.413 # Server initialized

7133:S 22 Aug 14:16:48.413 * Ready to accept connections

7133:S 22 Aug 14:16:48.413 * Connecting to MASTER 127.0.0.1:16379

7133:S 22 Aug 14:16:48.413 * MASTER SLAVE sync started

7133:S 22 Aug 14:16:48.414 * Non blocking connect for SYNC fired the event.

7133:S 22 Aug 14:16:48.414 * Master replied to PING, replication can continue...

7133:S 22 Aug 14:16:48.415 * Partial resynchronization not possible (no cached master)

7133:S 22 Aug 14:16:48.417 * Full resync from master: 211d3b4eceaa3af4fe5c77d22adf06e1218e0e7b:0

7133:S 22 Aug 14:16:48.494 * MASTER SLAVE sync: receiving 176 bytes from master

7133:S 22 Aug 14:16:48.495 * MASTER SLAVE sync: Flushing old data

7133:S 22 Aug 14:16:48.496 * MASTER SLAVE sync: Loading DB in memory

7133:S 22 Aug 14:16:48.498 * MASTER SLAVE sync: Finished with success

节点redis-36379$ cat /var/log/redis/redis-36379.log

7136:C 22 Aug 14:16:51.839 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo

7136:C 22 Aug 14:16:51.840 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=7136, just started

7136:C 22 Aug 14:16:51.841 # Configuration loaded

7137:S 22 Aug 14:16:51.843 * Increased maximum number of open files to 10032 (it was originally set to 256).

7137:S 22 Aug 14:16:51.845 * Running mode=standalone, port=36379.

7137:S 22 Aug 14:16:51.845 # Server initialized

7137:S 22 Aug 14:16:51.846 * Ready to accept connections

7137:S 22 Aug 14:16:51.846 * Connecting to MASTER 127.0.0.1:16379

7137:S 22 Aug 14:16:51.847 * MASTER SLAVE sync started

7137:S 22 Aug 14:16:51.847 * Non blocking connect for SYNC fired the event.

7137:S 22 Aug 14:16:51.847 * Master replied to PING, replication can continue...

7137:S 22 Aug 14:16:51.848 * Partial resynchronization not possible (no cached master)

7137:S 22 Aug 14:16:51.850 * Full resync from master: 211d3b4eceaa3af4fe5c77d22adf06e1218e0e7b:14

7137:S 22 Aug 14:16:51.923 * MASTER SLAVE sync: receiving 176 bytes from master

7137:S 22 Aug 14:16:51.923 * MASTER SLAVE sync: Flushing old data

7137:S 22 Aug 14:16:51.924 * MASTER SLAVE sync: Loading DB in memory

7137:S 22 Aug 14:16:51.927 * MASTER SLAVE sync: Finished with success

配置Sentinel:

1.4.3. Sentinel的配置管理

分别拷贝三份redis-sentinel.conf文件到/usr/local/redis-sentinel目录下面。三个配置文件分别对应master、slave1和slave2三个Redis节点的 哨兵配置。

$ sudo cp /usr/local/redis-4.0.11/sentinel.conf /usr/local/redis-sentinel/sentinel-16380.conf

$ sudo cp /usr/local/redis-4.0.11/sentinel.conf /usr/local/redis-sentinel/sentinel-26380.conf

$ sudo cp /usr/local/redis-4.0.11/sentinel.conf /usr/local/redis-sentinel/sentinel-36380.conf

节点1:sentinel-16380.confprotected-mode no

bind 0.0.0.0

port 16380

daemonize yes

sentinel monitor master 127.0.0.1 16379 2

sentinel down-after-milliseconds master 5000

sentinel failover-timeout master 180000

sentinel parallel-syncs master 1

sentinel auth-pass master 123456

logfile /var/log/redis/sentinel-16380.log

节点2:sentinel-26380.confprotected-mode no

bind 0.0.0.0

port 26380

daemonize yes

sentinel monitor master 127.0.0.1 16379 2

sentinel down-after-milliseconds master 5000

sentinel failover-timeout master 180000

sentinel parallel-syncs master 1

sentinel auth-pass master 123456

logfile /var/log/redis/sentinel-26380.log

节点3:sentinel-36380.confprotected-mode no

bind 0.0.0.0

port 36380

daemonize yes

sentinel monitor master 127.0.0.1 16379 2

sentinel down-after-milliseconds master 5000

sentinel failover-timeout master 180000

sentinel parallel-syncs master 1

sentinel auth-pass master 123456

logfile /var/log/redis/sentinel-36380.log

1.4.4. Sentinel启动验证

按顺序分别启动16380,26380和36380三个Sentinel节点,启动命令和启动日志如下:

$ sudo redis-sentinel /usr/local/redis-sentinel/sentinel-16380.conf

$ sudo redis-sentinel /usr/local/redis-sentinel/sentinel-26380.conf

$ sudo redis-sentinel /usr/local/redis-sentinel/sentinel-36380.conf

查看Sentinel的启动进程:

$ ps -ef | grep redis-sentinel

0  7954     1   0  3:30下午 ??         0:00.05 redis-sentinel 0.0.0.0:16380 [sentinel]

0  7957     1   0  3:30下午 ??         0:00.05 redis-sentinel 0.0.0.0:26380 [sentinel]

0  7960     1   0  3:30下午 ??         0:00.04 redis-sentinel 0.0.0.0:36380 [sentinel]

查看Sentinel的启动日志:

节点sentinel-16380$ cat /var/log/redis/sentinel-16380.log

7953:X 22 Aug 15:30:27.245 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo

7953:X 22 Aug 15:30:27.245 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=7953, just started

7953:X 22 Aug 15:30:27.245 # Configuration loaded

7954:X 22 Aug 15:30:27.247 * Increased maximum number of open files to 10032 (it was originally set to 256).

7954:X 22 Aug 15:30:27.249 * Running mode=sentinel, port=16380.

7954:X 22 Aug 15:30:27.250 # Sentinel ID is 69d05b86a82102a8919231fd3c2d1f21ce86e000

7954:X 22 Aug 15:30:27.250 # +monitor master master 127.0.0.1 16379 quorum 2

7954:X 22 Aug 15:30:32.286 # +sdown sentinel fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7 127.0.0.1 36380 @ master 127.0.0.1 16379

7954:X 22 Aug 15:30:34.588 # -sdown sentinel fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7 127.0.0.1 36380 @ master 127.0.0.1 16379

sentinel-16380节点的Sentinel ID为69d05b86a82102a8919231fd3c2d1f21ce86e000,并通过Sentinel ID把自身加入sentinel集群中。

节点sentinel-26380$ cat /var/log/redis/sentinel-26380.log

7956:X 22 Aug 15:30:30.900 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo

7956:X 22 Aug 15:30:30.901 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=7956, just started

7956:X 22 Aug 15:30:30.901 # Configuration loaded

7957:X 22 Aug 15:30:30.904 * Increased maximum number of open files to 10032 (it was originally set to 256).

7957:X 22 Aug 15:30:30.905 * Running mode=sentinel, port=26380.

7957:X 22 Aug 15:30:30.906 # Sentinel ID is 21e30244cda6a3d3f55200bcd904d0877574e506

7957:X 22 Aug 15:30:30.906 # +monitor master master 127.0.0.1 16379 quorum 2

7957:X 22 Aug 15:30:30.907 * +slave slave 127.0.0.1:26379 127.0.0.1 26379 @ master 127.0.0.1 16379

7957:X 22 Aug 15:30:30.911 * +slave slave 127.0.0.1:36379 127.0.0.1 36379 @ master 127.0.0.1 16379

7957:X 22 Aug 15:30:36.311 * +sentinel sentinel fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7 127.0.0.1 36380 @ master 127.0.0.1 16379

sentinel-26380 节点的 Sentinel ID 为 21e30244cda6a3d3f55200bcd904d0877574e506,并通过 Sentinel ID 把自身加入 sentinel 集群中。此时 sentinel 集群中已有 sentinel-16380 和 sentinel-26380 两个节点。

节点sentinel-36380$ cat /var/log/redis/sentinel-36380.log

7959:X 22 Aug 15:30:34.273 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo

7959:X 22 Aug 15:30:34.274 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=7959, just started

7959:X 22 Aug 15:30:34.274 # Configuration loaded

7960:X 22 Aug 15:30:34.276 * Increased maximum number of open files to 10032 (it was originally set to 256).

7960:X 22 Aug 15:30:34.277 * Running mode=sentinel, port=36380.

7960:X 22 Aug 15:30:34.278 # Sentinel ID is fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7

7960:X 22 Aug 15:30:34.278 # +monitor master master 127.0.0.1 16379 quorum 2

7960:X 22 Aug 15:30:34.279 * +slave slave 127.0.0.1:26379 127.0.0.1 26379 @ master 127.0.0.1 16379

7960:X 22 Aug 15:30:34.283 * +slave slave 127.0.0.1:36379 127.0.0.1 36379 @ master 127.0.0.1 16379

7960:X 22 Aug 15:30:34.993 * +sentinel sentinel 21e30244cda6a3d3f55200bcd904d0877574e506 127.0.0.1 26380 @ master 127.0.0.1 16379

sentinel-36380 节点的 Sentinel ID 为 fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7,并通过 Sentinel ID 把自身加入 sentinel 集群中。此时 sentinel 集群中已有 sentinel-16380,sentinel-26380 和 sentinel-36380 三个节点。

1.4.5. Sentinel配置刷新(这里注意一下,sentinel的配置文件是自动刷新的)

sentinel-16380.conf文件新生成如下的配置项:# Generated by CONFIG REWRITE

dir "/usr/local/redis-sentinel"

sentinel config-epoch master 0

sentinel leader-epoch master 0

sentinel known-slave master 127.0.0.1 36379

sentinel known-slave master 127.0.0.1 26379

sentinel known-sentinel master 127.0.0.1 26380 21e30244cda6a3d3f55200bcd904d0877574e506

sentinel known-sentinel master 127.0.0.1 36380 fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7

sentinel current-epoch 0

可以注意到,sentinel-16380.conf 刷新写入了 Redis 主节点关联的所有 从节点 redis-26379 和 redis-36379,同时写入了其余两个 Sentinel 节点 sentinel-26380 和 sentinel-36380 的 IP 地址,端口号 和 Sentinel ID。# Generated by CONFIG REWRITE

dir "/usr/local/redis-sentinel"

sentinel config-epoch master 0

sentinel leader-epoch master 0

sentinel known-slave master 127.0.0.1 26379

sentinel known-slave master 127.0.0.1 36379

sentinel known-sentinel master 127.0.0.1 36380 fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7

sentinel known-sentinel master 127.0.0.1 16380 69d05b86a82102a8919231fd3c2d1f21ce86e000

sentinel current-epoch 0

可以注意到,sentinel-26380.conf 刷新写入了 Redis 主节点关联的所有 从节点 redis-26379 和 redis-36379,同时写入了其余两个 Sentinel 节点 sentinel-36380 和 sentinel-16380 的 IP 地址,端口号 和 Sentinel ID。# Generated by CONFIG REWRITE

dir "/usr/local/redis-sentinel"

sentinel config-epoch master 0

sentinel leader-epoch master 0

sentinel known-slave master 127.0.0.1 36379

sentinel known-slave master 127.0.0.1 26379

sentinel known-sentinel master 127.0.0.1 16380 69d05b86a82102a8919231fd3c2d1f21ce86e000

sentinel known-sentinel master 127.0.0.1 26380 21e30244cda6a3d3f55200bcd904d0877574e506

sentinel current-epoch 0

可以注意到,sentinel-36380.conf 刷新写入了 Redis 主节点关联的所有 从节点 redis-26379 和 redis-36379,同时写入了其余两个 Sentinel 节点 sentinel-16380 和 sentinel-26380 的 IP 地址,端口号 和 Sentinel ID。

1.5. Sentinel时客户端命令

检查其他 Sentinel 节点的状态,返回 PONG 为正常。

> PING sentinel

显示被监控的所有 主节点 以及它们的状态。

> SENTINEL masters

显示指定 主节点 的信息和状态。

> SENTINEL master

显示指定 主节点 的所有 从节点 以及它们的状态。

> SENTINEL slaves

返回指定 主节点 的 IP 地址和 端口。如果正在进行 failover 或者 failover 已经完成,将会显示被提升为 主节点 的 从节点 的 IP 地址和 端口。

> SENTINEL get-master-addr-by-name

重置名字匹配该 正则表达式 的所有的 主节点 的状态信息,清除它之前的 状态信息,以及 从节点 的信息。

> SENTINEL reset

强制当前 Sentinel 节点执行 failover,并且不需要得到其他 Sentinel 节点的同意。但是 failover 后会将 最新的配置 发送给其他 Sentinel 节点。

>SENTINEL failover

2. Redis Sentinel故障切换与恢复

2.1. Redis CLI客户端跟踪

上面的日志显示,redis-16379节点为主节点,它的进程ID为7127。为了模拟Redis主节点故障,强制杀掉这个进程。

$ kill -9 7127

使用redis-cli客户端命令进入sentinel-16380节点,查看Redis节点的状态信息。

$ redis-cli -p 16380

查看Redis主从集群的主节点信息。可以发现redis-26379晋升为新的主节点。127.0.0.1:16380> SENTINEL master master

1) "name"

2) "master"

3) "ip"

4) "127.0.0.1"

5) "port"

6) "26379"

7) "runid"

8) "b8ca3b468a95d1be5efe1f50c50636cafe48c59f"

9) "flags"

10) "master"

11) "link-pending-commands"

12) "0"

13) "link-refcount"

14) "1"

15) "last-ping-sent"

16) "0"

17) "last-ok-ping-reply"

18) "588"

19) "last-ping-reply"

20) "588"

21) "down-after-milliseconds"

22) "5000"

23) "info-refresh"

24) "9913"

25) "role-reported"

26) "master"

27) "role-reported-time"

28) "663171"

29) "config-epoch"

30) "1"

31) "num-slaves"

32) "2"

33) "num-other-sentinels"

34) "2"

35) "quorum"

36) "2"

37) "failover-timeout"

38) "180000"

39) "parallel-syncs"

40) "1"

2.2. Redis Sentinel日志跟踪

查看任意Sentinel节点的日志如下:7954:X 22 Aug 18:40:22.504 # +tilt #tilt mode entered

7954:X 22 Aug 18:40:32.197 # +tilt #tilt mode entered

7954:X 22 Aug 18:41:02.241 # -tilt #tilt mode exited

7954:X 22 Aug 18:48:24.550 # +sdown master master 127.0.0.1 16379

7954:X 22 Aug 18:48:24.647 # +new-epoch 1

7954:X 22 Aug 18:48:24.651 # +vote-for-leader fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7 1

7954:X 22 Aug 18:48:25.678 # +odown master master 127.0.0.1 16379 #quorum 3/2

7954:X 22 Aug 18:48:25.678 # Next failover delay: I will not start a failover before Wed Aug 22 18:54:24 2018

7954:X 22 Aug 18:48:25.709 # +config-update-from sentinel fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7 127.0.0.1 36380 @ master 127.0.0.1 16379

7954:X 22 Aug 18:48:25.710 # +switch-master master 127.0.0.1 16379 127.0.0.1 26379

7954:X 22 Aug 18:48:25.710 * +slave slave 127.0.0.1:36379 127.0.0.1 36379 @ master 127.0.0.1 26379

7954:X 22 Aug 18:48:25.711 * +slave slave 127.0.0.1:16379 127.0.0.1 16379 @ master 127.0.0.1 26379

7954:X 22 Aug 18:48:30.738 # +sdown slave 127.0.0.1:16379 127.0.0.1 16379 @ master 127.0.0.1 26379

7954:X 22 Aug 19:38:23.479 # -sdown slave 127.0.0.1:16379 127.0.0.1 16379 @ master 127.0.0.1 26379

分析日志,可以发现redis-16329节点先进入sdown主观下线状态。

+sdown master master 127.0.0.1 16379

哨兵检测到redis-16329出现故障,Sentinel进入一个新纪元,从0变为1。

+new-epoch 1

三个Sentinel节点开始协商主节点的状态,判断其是否需要客观下线。

+vote-for-leader fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7 1

超过quorum个数的Sentinel节点认为主节点出现故障,redis-16329节点进入客观下线状态。

+odown master master 127.0.0.1 16379 #quorum 3/2

Sentinal进行自动故障切换,协商选定redis-26329节点作为新的主节点。

+switch-master master 127.0.0.1 16379 127.0.0.1 26379

redis-36329节点和已经客观下线的redis-16329节点成为redis-26479的从节点。

7954:X 22 Aug 18:48:25.710 * +slave slave 127.0.0.1:36379 127.0.0.1 36379 @ master 127.0.0.1 26379

7954:X 22 Aug 18:48:25.711 * +slave slave 127.0.0.1:16379 127.0.0.1 16379 @ master 127.0.0.1 26379

2.3. Redis的配置文件(自动刷新的)

分别查看三个redis节点的配置文件,发生主从切换时redis.conf的配置会自动发生刷新。

节点 redis-16379daemonize yes

pidfile "/var/run/redis-16379.pid"

logfile "/var/log/redis/redis-16379.log"

port 16379

bind 0.0.0.0

timeout 300

databases 16

dbfilename "dump-16379.db"

dir "/usr/local/redis-sentinel/redis-workdir"

masterauth "123456"

requirepass "123456"

节点 redis-26379daemonize yes

pidfile "/var/run/redis-26379.pid"

logfile "/var/log/redis/redis-26379.log"

port 26379

bind 0.0.0.0

timeout 300

databases 16

dbfilename "dump-26379.db"

dir "/usr/local/redis-sentinel/redis-workdir"

masterauth "123456"

requirepass "123456"

节点 redis-36379daemonize yes

pidfile "/var/run/redis-36379.pid"

logfile "/var/log/redis/redis-36379.log"

port 36379

bind 0.0.0.0

timeout 300

databases 16

dbfilename "dump-36379.db"

dir "/usr/local/redis-sentinel/redis-workdir"

masterauth "123456"

requirepass "123456"

slaveof 127.0.0.1 26379

分析:redis-26379 节点 slaveof 配置被移除,晋升为 主节点。redis-16379 节点处于 宕机状态。redis-36379 的 slaveof 配置更新为 127.0.0.1 redis-26379,成为 redis-26379 的 从节点。

重启节点redis-16379。待正常启动后,再次查看它的redis.conf文件,配置如下:daemonize yes

pidfile "/var/run/redis-16379.pid"

logfile "/var/log/redis/redis-16379.log"

port 16379

bind 0.0.0.0

timeout 300

databases 16

dbfilename "dump-16379.db"

dir "/usr/local/redis-sentinel/redis-workdir"

masterauth "123456"

requirepass "123456"

# Generated by CONFIG REWRITE

slaveof 127.0.0.1 26379

节点redis-16379的配置文件新增一行slaveof配置属性,指向redis-26379,即成为新的主节点的从节点。

小结

本文首先对 Redis 实现高可用的几种模式做出了阐述,指出了 Redis 主从复制 的不足之处,进一步引入了 Redis Sentinel 哨兵模式 的相关概念,深入说明了 Redis Sentinel 的 具体功能,基本原理,高可用搭建 和 自动故障切换 验证等。

当然,Redis Sentinel 仅仅解决了 高可用 的问题,对于 主节点 单点写入和单节点无法扩容等问题,还需要引入 Redis Cluster 集群模式 予以解决。

3.哨兵节点管理

3.1 哨兵节点的增加和删除

增加sentinal,会自动发现

删除sentinal的步骤

(1)停止sentinal进程

(2)SENTINEL RESET *,在所有sentinal上执行,清理所有的master状态

(3)SENTINEL MASTER mastername,在所有sentinal上执行,查看所有sentinal对数量是否达成了一致

3.2 slave的永久下线

让master摘除某个已经下线的slave:SENTINEL RESET mastername,在所有的哨兵上面执行

3.3 slave切换为Master的优先级

slave->master选举优先级:slave-priority,值越小优先级越高

3.4 基于哨兵集群架构下的安全认证

每个slave都有可能切换成master,所以每个实例都要配置两个指令

master上启用安全认证,requirepass

master连接口令,masterauth

sentinal,sentinel auth-pass

3.5 容灾演练

通过哨兵看一下当前的master:SENTINEL get-master-addr-by-name mymaster

把master节点kill -9掉,pid文件也删除掉

查看sentinal的日志,是否出现+sdown字样,识别出了master的宕机问题; 然后出现+odown字样,就是指定的quorum哨兵数量,都认为master宕机了

(1)三个哨兵进程都认为master是sdown了

(2)超过quorum指定的哨兵进程都认为sdown之后,就变为odown

(3)哨兵1是被选举为要执行后续的主备切换的那个哨兵

(4)哨兵1去新的master(slave)获取了一个新的config version

(5)尝试执行failover

(6)投票选举出一个slave区切换成master,每个哨兵都会执行一次投票

(7)让salve,slaveof noone,不让它去做任何节点的slave了; 把slave提拔成master; 旧的master认为不再是master了

(8)哨兵就自动认为之前的187:6379变成了slave了,19:6379变成了master了

(9)哨兵去探查了一下187:6379这个salve的状态,认为它sdown了

所有哨兵选举出了一个,来执行主备切换操作

如果哨兵的majority都存活着,那么就会执行主备切换操作

再通过哨兵看一下master:SENTINEL get-master-addr-by-name mymaster

尝试连接一下新的master

故障恢复,再将旧的master重新启动,查看是否被哨兵自动切换成slave节点

(1)手动杀掉master

(2)哨兵能否执行主备切换,将slave切换为master

(3)哨兵完成主备切换后,新的master能否使用

(4)故障恢复,将旧的master重新启动

(5)哨兵能否自动将旧的master变为slave,挂接到新的master上面去,而且也是可以使用的

主从架构,单master的瓶颈:

能够存储多少数据量,受限于master

怎么横向扩展,master:

我们可以做多个redis 主从集群,做业务的分流,不同的请求,访问到不同的master

redis cluster帮我们做好了这样的功能:

可以支撑N个redis master node,每个master node都可以挂载多个slave node

redis cluster (多master + 读写分离 + 高可用)

redis cluster 是用来支撑海量数据的

ip地址转换数字函数 iton_redis深度剖析: 03 redis读写哨兵模式相关推荐

  1. ip地址转换数字函数 iton_DataLakeAnalytics: 解析IP地址对应的国家城市的函数

    Data Lake Analytics 作为云上数据处理的枢纽,最近加入了通过IP地址查找对应的国家.省份.城市.ISP的函数, 今天带大家体验一下. 函数详细介绍 本次一共添加了下面这些函数: ip ...

  2. ip地址转换数字函数 iton_IP 地址转换(在点分格式和数字之间相互转换)

    MySQL 中的内的 IP 地址转换函数: 1. IP 由点分格式,转换为数字格式.mysql> select inet_aton('202.96.128.68'); +------------ ...

  3. ip地址转换数字函数 iton_IP地址的字符串形式和数字形式之间的相互转换函数

    最近要用到网络编程的东西,差一点自己去山寨已有的函数.基础不好,不知道已有函数可以满足需要,呵呵. 这个示例程序说的是ip地址的数字形式和字符串形式之间的相互转换. 从字符串形式转换到数字形式: in ...

  4. ip地址转换数字函数 iton_PHP中IP地址与整型数字互相转换详解

    IP转换成整型存储是数据库优化一大趋势,不少人目前存储IP时还在使用字符串类型存储,字符串索引比整型索引消耗资源很多,特别是表中数据量大的时候,以及求查询某一个ip段的数据,今天说的ip是指ip4,i ...

  5. ip地址转换数字函数 iton_数字转IP地址函数

    -- 数字转 IP 地址函数: IF OBJECT_ID ( 'dbo.fn_IP2Str' )> 0 DROP FUNCTION dbo . fn_IP2Str GO CREATE FUNCT ...

  6. ip地址转换数字函数 iton_字符串IP地址转换成IP数值函数

    if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[f_IP2Int]') and xtype in (N'FN ...

  7. ip地址转换数字函数 iton_esp8266 inet_ntoa函数实现 ip地址转换为字符串 MAC地址转字符串...

    esp8266芯片可作为mcu,功能很强大,但与传统mcu相比,可用资源实在不多,连浮点数都不支持 IP地址转字符创函数inet_ntoa很方便,但8266中没有!!!!! 本节将讲述如何自己实现in ...

  8. ip地址转换数字函数 iton_IP地址转换函数

    在ASCII字符串("192.168.0.99")与网络字节序的二进制值间转换地址. 涉及函数的头文件为#include 一.只适用于IPv4协议的函数: int inet_ato ...

  9. ip地址转换数字函数 iton_3. IP地址转换函数

    一.字符串表示的IP地址需要被转化为整数(二进制数)方能使用 IPv4地址:点分十进制字符串 IPv6地址:十六进制字符串 有时(如记录日志),我们则要把整数(二进制数)表示的IP地址转化为可读的字符 ...

最新文章

  1. vue调用接口获取后台数据_Vuex 存储||获取后台接口数据
  2. c语言计算机二级资料,2016年计算机二级C语言复习资料汇总
  3. 基于Verilog的按键控制LED灯
  4. c++用牛顿法开多次根_望远镜的历史之三:大神出世,改变望远镜历史的竟然是牛顿...
  5. 计算机路表配置命令,计算机、华为交换机、路由器配置命令表
  6. matlab画一个电动机系统图,基于MATLABGUI的电机学仿真实验系统设计
  7. Java ConcurrentHashMap 最佳实践
  8. 深入了解C++变量类型有哪些
  9. configure: line syntax error near unexpected token `win32-dll'
  10. grafana 中国地图 echarts
  11. 电脑没有声音怎么安装声卡驱动?驱动人生声卡驱动安装失败原因
  12. 简笔画花边边框超简单_好看的花边边框简笔画
  13. Python3 async def和@asyncio.coroutine的区别
  14. HTC Vive榜单:盘点一周最受欢迎的VR应用
  15. 超有用:记一次Yapi上传报错及其处理方式
  16. VSCode配置编译MSVC程序
  17. 打开新页打开企业邮箱FOXMAIL常见错误提示“Message format error”
  18. 搜苹果ipad版_优秀的文本笔记工具 Keep It 苹果软件破解版
  19. 孩子学python_【二孩家庭要注意什么】二孩家庭要怎么教育_二孩家庭的孩子最好间隔几岁 - 妈妈网百科...
  20. 一个30岁男人的爱情婚姻思考(尽量不要在学习的时间看)

热门文章

  1. mes系统质量管理通常是怎样运行的?
  2. Elastic 今日在纽交所上市,股价最高暴涨122%。
  3. 【Bex5】代码片段-2023年01月10日
  4. http和ftp协议的区别
  5. 用Python端对端数据分析识别机器人“僵尸粉”
  6. java对对碰游戏设计报告_手把手带你用Java打造一款对对碰游戏(下篇)
  7. Candence PCB Allegro⑤DRC、光绘及其他命令
  8. PMBOK指南第六版与第五版的区别在哪里?
  9. Linux操作系统——Linux可视化管理-webmin 和 bt 运维工具
  10. STM32F1与STM32CubeIDE编程实例-HMC5883电子罗盘驱动