做运维需要了解哪些Redis数据库知识?(下)

五、Redis主从复制

5.1 redis复制特性

a 使用异步复制。

b 一个主服务器可以有多个从服务器。

c 从服务器也可以有自己的从服务器。

d 复制功能不会阻塞主服务器。

e 可以通过复制功能来让主服务器免于执行持久化操作,由从服务器去执行持久化操作即可。

关闭主服务器持久化时,复制功能的数据安全

当配置Redis复制功能时,强烈建议打开主服务器的持久化功能。否则的话,由于延迟等问题,部署的服务应该要避免自动拉起。

为了帮助理解主服务器关闭持久化时自动拉起的危险性,参考一下以下会导致主从服务器数据全部丢失的例子:

1. 假设节点A为主服务器,并且关闭了持久化。并且节点B和节点C从节点A复制数据

2. 节点A崩溃,然后由自动拉起服务重启了节点A。由于节点A的持久化被关闭了,所以重启之后没有任何数据

3. 节点B和节点C将从节点A复制数据,但是A的数据是空的,于是就把自身保存的数据副本删除

在关闭主服务器上的持久化,并同时开启自动拉起进程的情况下,即便使用Sentinel来实现Redis的高可用性,也是非常危险的。因为主服务器可能拉起得非常快,以至于Sentinel在配置的心跳时间间隔内没有检测到主服务器已被重启,然后还是会执行上面的数据丢失的流程。

无论何时,数据安全都是极其重要的,所以应该禁止主服务器关闭持久化的同时自动拉起。

5.2 主从复制原理

redis 主从同步有两种方式(或者所两个阶段):全同步和部分同步。

主从刚刚连接的时候,进行全同步;全同步结束后,进行部分同步。当然,如果有需要,slave 在任何时候都可以发起全同步。

redis 策略是,无论如何,首先会尝试进行部分同步,如不成功,要求从机进行全同步,并启动 BGSAVE……BGSAVE 结束后,传输 RDB 文件;如果成功,允许从机进行部分同步,并传输积压空间中的数据。

下面这幅图,总结了主从同步的机制:

主从复制原理:

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

2. 接到 SYNC 命令的主服务器会调用BGSAVE 命令,创建一个 RDB 文件,并使用缓冲区记录接下来执行的所有写命令。

3. 当主服务器执行完 BGSAVE 命令时,它会向从服务器发送 RDB 文件,而从服务器则会接收并载入这个文件。

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

命令的传播:

在主从服务器完成同步之后,主服务器每执行一个写命令,它都会将被执行的写命令发送给从服务器执行,这个操作被称为“命令传播”(command propagate)。

命令传播是一个持续的过程:只要复制仍在继续,命令传播就会一直进行,使得主从服务器的状态可以一直保持一致。

5.3 复制中的SYNC与PSYNC

在 Redis 2.8 版本之前,断线之后重连的从服务器总要执行一次完整重同步(full resynchronization)操作。

从 Redis 2.8 开始,Redis 使用 PSYNC命令代替 SYNC 命令。PSYNC 比起 SYNC 的最大改进在于 PSYNC 实现了部分重同步(partial resync)特性:在主从服务器断线并且重新连接的时候,只要条件允许,PSYNC 可以让主服务器只向从服务器同步断线期间缺失的数据,而不用重新向从服务器同步整个数据库。

5.4 复制的一致性问题

在读写分离环境下,客户端向主服务器发送写命令 SET n 10086,主服务器在执行这个写命令之后,向客户端返回回复,并将这个写命令传播给从服务器。

接到回复的客户端继续向从服务器发送读命令 GET n ,并且因为网络状态的原因,客户端的 GET命令比主服务器传播的 SET 命令更快到达了从服务器。

因为从服务器键 n 的值还未被更新,所以客户端在从服务器读取到的将是一个错误(过期)的 n值。

5.5 复制安全性提升

主服务器只在有至少 N 个从服务器的情况下,才执行写操作从 Redis 2.8 开始,为了保证数据的安全性,可以通过配置,让主服务器只在有至少 N 个当前已连接从服务器的情况下,才执行写命令。

不过,因为 Redis 使用异步复制,所以主服务器发送的写数据并不一定会被从服务器接收到,因此,数据丢失的可能性仍然是存在的。

通过以下两个参数保证数据的安全:

5.6 Redis主从复制实践

在安装redis时就进行了多实例的配置

配置文件示例:

启动:

复制环境说明:

主节点:6380

从节点:6381、6382

开启主从(在6381 6382实例中执行)

至此redis主从复制完成

5.7 Redis主从复制管理

主从复制状态监控:info replication

主从切换: slaveof no one

六、Redis HA 实践(Redis Sentinel)

Redis-Sentinel是Redis官方推荐的高可用性(HA)解决方案,当用Redis做Master-slave的高可用方案时,假如master宕机了,Redis本身(包括它的很多客户端)都没有实现自动进行主备切换,而Redis-sentinel本身也是一个独立运行的进程,它能监控多个master-slave集群,发现master宕机后能进行自动切换。

Sentinel 是一个监视器,它可以根据被监视实例的身份和状态来判断应该执行何种动作。

6.1 Redis Sentinel 功能

监控(Monitoring):

Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。

提醒(Notification):

当被监控的某个 Redis 服务器出现问题时,Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。

自动故障迁移(Automatic failover):

当一个主服务器不能正常工作时,Sentinel 会开始一次自动故障迁移操作,它会将失效主服务器的其中一个从服务器升级为新的主服务器,并让失效主服务器的其他从服务器改为复制新的主服务器;当客户端试图连接失效的主服务器时,集群也会向客户端返回新主服务器的地址,使得集群可以使用新主服务器代替失效服务器。

6.2 服务器连接

发现并连接主服务器:

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

Sentinel 会与被监视的主服务器创建

两个网络连接:

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

订阅连接用于订阅指定的频道,从而发现监视同一主服务器的其他 Sentinel。

发现并连接从服务器:

Sentinel 通过向主服务器发送 INFO 命令来自动获得所有从服务器的地址。

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

发现其他 Sentinel:

Sentinel 会通过命令连接向被监视的主从服务器发送“HELLO” 信息,该消息包含Sentinel 的 IP、端口号、ID 等内容,以此来向其他 Sentinel 宣告自己的存在。与此同时Sentinel会通过订阅连接接收其他 Sentinel 的“HELLO”信息,以此来发现监视同一个主服务器的其他 Sentinel 。

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

多个Sentienl之间的链接:

Sentinel 之间只会互相创建命令连接,用于进行通信。因为已经有主从服务器作为发送和接收 HELLO 信息的中介,所以 Sentinel之间不会创建订阅连接。

6.3 检测实例的状态

Sentinel 使用 PING 命令来检测实例的状态:如果实例在指定的时间内没有返回回复,或者返回错误的回复,那么该实例会被Sentinel 判断为下线。

Redis 的 Sentinel 中关于下线(down)有两个不同的概念:

主观下线(Subjectively Down,简称 SDOWN)指的是单个Sentinel 实例对服务器做出的下线判断。

客观下线(Objectively Down,简称 ODOWN)指的是多个Sentinel 实例在对同一个服务器做出 SDOWN 判断,并且通过SENTINEL is-master-down-by-addr 命令互相交流之后,得出的服务器下线判断。(一个 Sentinel 可以通过向另一个Sentinel 发送SENTINEL is-master-down-by-addr 命令来询问对方是否认为给定的服务器已下线。)

如果一个服务器没有在 master-down-after-milliseconds 选项所指定的时间内,对向它发送 PING 命令的 Sentinel 返回一个有效回复(valid reply),那么 Sentinel 就会将这个服务器标记为主观下线。

6.4 故障转移FAILOVER

一次故障转移操作由以下步骤组成:

1. 发现主服务器已经进入客观下线状态。

2. 基于Raft leader election 协议,进行投票选举

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

4. 选出一个从服务器,并将它升级为主服务器。

5. 向被选中的从服务器发送 SLAVEOF NO ONE 命令,让它转变为主服务器。

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

7.向已下线主服务器的从服务器发送 SLAVEOF 命令,让它们去复制新的主服务器。

8.当所有从服务器都已经开始复制新的主服务器时,leader Sentinel 终止这次故障迁移操作。

6.5 配置sentinel

创建程序目录

编辑配置文件

启动sentinel

配置文件说明

6.6 Sentinel命令操作

6.7 Sentinel发布与订阅信息

客户端可以将 Sentinel 看作是一个只提供了订阅功能的 Redis 服务器:你不可以使用 PUBLISH 命令向这个服务器发送信息,但你可以用 SUBSCRIBE 命令或者 PSUBSCRIBE 命令,通过订阅给定的频道来获取相应的事件提醒。

一个频道能够接收和这个频道的名字相同的事件。比如说,名为 +sdown 的频道就可以接收所有实例进入主观下线(SDOWN)状态的事件。

通过执行 PSUBSCRIBE * 命令可以接收所有事件信息。

以下列出的是客户端可以通过订阅来获得的频道和信息的格式:

第一个英文单词是频道/事件的名字,其余的是数据的格式。

注意, 当格式中包含 instance details 字样时, 表示频道所返回的信息中包

含了以下用于识别目标实例的内容:

七、Redis cluster

7.1 Redis集群

Redis 集群是一个可以在多个 Redis 节点之间进行数据共享的设施(installation)。

Redis 集群不支持那些需要同时处理多个键的 Redis 命令,因为执行这些命令需要在多个 Redis 节点之间移动数据,并且在高负载的情况下,这些命令将降低 Redis 集群的性能,并导致不可预测的行为。

Redis 集群通过分区(partition)来提供一定程度的可用性(availability):即使集群中有一部分节点失效或者无法进行通讯,集群也可以继续处理命令请求。将数据自动切分(split)到多个节点的能力。

当集群中的一部分节点失效或者无法进行通讯时,仍然可以继续处理命令请求的能力。

7.2 Redis 集群数据共享

Redis 集群使用数据分片(sharding)而非一致性哈希(consistency hashing)来实现:一个 Redis 集群包含 16384 个哈希槽(hash slot),数据库中的每个键都属于这 16384 个哈希槽的其中一个,集群使用公式CRC16(key) % 16384 来计算键 key 属于哪个槽,其中 CRC16(key) 语句用于计算键 key 的 CRC16 校验和 。

节点 A 负责处理 0 号至 5500 号哈希槽。

节点 B 负责处理 5501 号至 11000 号哈希槽。

节点 C 负责处理 11001 号至 16384 号哈希槽。

槽的计算公式

集群使用公式 CRC16(key) & 16383 计算键 key属于哪个槽。

7.3 集群运行机制

所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。

节点的fail是通过集群中超过半数的master节点检测失效时才失效。

客户端与redis节点直连,不需要中间proxy层。客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可

把所有的物理节点映射到[0-16383]slot上,cluster 负责维护nodeslotkey

为了使得集群在一部分节点下线或者无法与集群的大多数(majority)节点进行通讯的情况下,仍然可以正常运作,Redis 集群对节点使用了主从复制功能:集群中的每个节点都有 1 个至 N 个复制品(replica),其中一个复制品为主节点(master),而其余的N-1 个复制品为从节点(slave)。

在之前列举的节点 A 、B 、C 的例子中,如果节点 B 下线了,那么集群将无法正常运行,因为集群找不到节点来处理5501号至11000号的哈希槽。

假如在创建集群的时候(或者至少在节点 B下线之前),我们为主节点B添加了从节点 B1,那么当主节点 B下线的时候,集群就会将B1设置为新的主节点,并让它代替下线的主节点B,继续处理5501号至11000号的哈希槽,这样集群就不会因为主节点B的下线而无法正常运作了。

不过如果节点B和B1都下线的话,Redis集群还是会停止运作。

集群的复制特性重用了 SLAVEOF 命令的代码,所以集群节点的复制行为和SLAVEOF 命令的复制行为完全相同。

7.4 集群的故障转移

1. 在集群里面,节点会对其他节点进行下线检测。

2. 当一个主节点下线时,集群里面的其他主节点负责对下线主节点进行故障移。

3. 换句话说,集群的节点集成了下线检测和故障转移等类似 Sentinel 的功能。

4. 因为 Sentinel 是一个独立运行的监控程序,而集群的下线检测和故障转移等功能是集成在节点里面的,它们的运行模式非常地不同,所以尽管这两者的功能很相似,但集群的实现没有重用 Sentinel 的代码。

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

命令发送到了正确的节点:

命令要处理的键所在的槽正好是由接收命令的节点负责,那么该节点执行命令,就像单机 Redis 服务器一样。

键 date 位于 2022 槽,该槽由节点 7000 负责,命令会直接执行。

命令发送到了错误的节点:

接收到命令的节点并非处理键所在槽的节点,那么节点将向客户端返回一个转向(redirection)错误,告知客户端应该到哪个节点去执行这个命令,客户端会根据错误提示的信息,重新向正确的节点发送命令。

键 date 位于 2022 槽,该槽由节点 7000 负责,但错误发送到了7001节点,7001向客户返回转向错误。

客户端根据转向错误的指引,转向到节点7000,并重新发送命令

7.5 关于转向错误

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

集群中的每个节点都会记录 16384 个槽分别由哪个节点负责,从而形成一个“槽表”(slot table)。

节点在接收到命令请求时,会通过槽表检查键所在的槽是否由本节点处理:

如果是的话,那么节点直接执行命令;

如果不是的话,那么节点就从槽表里面提取出正确节点的地址信息,然后返回转向错误。

7.6 配置集群

前期准备

# EPEL源安装ruby支持

使用国内源

配置文件

Redis 集群由多个运行在集群模式(cluster mode)下的 Redis 实例组成,实例的集群模式需要通过配置来开启,开启集群模式的实例将可以使用集群特有的功能和命令。

以下是一个包含了最少选项的集群配置文件示例:

创建程序目录

拷贝应用

创建配置文件

启动redis集群

创建集群

给定 redis-trib.rb 程序的命令是 create,这表示我们希望创建一个新的集群。

选项 --replicas 1 表示我们希望为集群中的每个主节点创建一个从节点。

7.7 集群管理

写数据,查看集群状态

重新分片实践

集群状态

故障转移

查看状态

增加新的节点

删除一个节点

删除master节点之前首先要使用reshard移除master的全部slot,然后再删除当前节点

添加一个从节点

7.8 状态说明

集群最近一次向节点发送 PING 命令之后,过去了多长时间还没接到回复。

节点最近一次返回 PONG 回复的时间。

节点的配置节点(configuration epoch)

本节点的网络连接情况:例如 connected 。

节点目前包含的槽:例如 127.0.0.1:7001 目前包含号码为 5960 至 10921 的哈希槽。

八、Redis API

8.1 PHP使用redis

连接测试代码

字符串操作

8.2 Python连接redis

安装软件包

测试

本文内容来自 老男孩Linux云计算运维优秀学员课后笔记整理

看完本文有收获?那就分享给更多朋友吧~

长按下方二维码,关注我哟

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181122G1QQQO00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券