Redis第三天

Redis第三天

    • 主从模式
      • 旧版同步
      • 新版重同步
      • 心跳检测
    • SENTINEL模式
      • 实例下线
        • 选举领头SENTINEL(Raft算法)
        • 故障转移
    • 集群
      • 集群的结构
      • CLUSTER MEET实现
      • 分片
        • 重新分片
      • 集群中的主从模式
        • 设置从节点
        • 监听和故障转移
      • 通信
    • Redis常用功能
      • 事务
      • 慢查询日志
      • 监听器

主从模式

用户可以通过SLAVEOF host port 或者设置slaveof选项,让一个服务器去复制另一个服务器,复制功能包括同步和命令传播,同步用于将从服务器状态更新为主服务器状态,传播用于在主服务器数据库状态被修改时,让主从服务器状态回到一致。

旧版同步

从服务器向主服务器发送SYNC命令,主服务器执行BGSAVE命令,生成一个RDB文件,并使用一个缓冲区记录从现在开始执行的所有写命令,将RDB文件发送给从服务器,从服务器接收并载入RDB文件,主服务器将缓冲区中的写命令发送给从服务器,保证两边数据库状态一致。

缺点:效率低下

新版重同步

使用PSYNC同步,初次复制时完整重同步,断线后使用部分重同步

部分重同步主要依赖三个变量

  1. 主从服务器的复制偏移量
  2. 主服务器的复制积压缓冲区
  3. 服务器的运行ID

主服务器维护了一个固定长度先进先出队列,默认大小为1MB的复制积压缓冲区,并且复制积压缓冲区会为队列中每个字节记录相应的复制偏移量,如果从服务器的偏移量之后的数据仍在复制积压缓冲区内,则执行部分重同步,否则执行完整重同步,执行同步之后会判断从服务器的ID是否与主服务器一致,不一致则执行完整重同步。

通过repl_backlog_size修改缓冲区大小

从服务器发送PSYNC命令

  • PSYNC < runid > (主服务器ID) < offset > (从服务器偏移量)
  • PSYNC ?-1 没有复制过任何主服务器时发送的同步命令

如果主服务器返回

  • + FULL RESYNC < runid > (主服务器ID) < offset > (主服务器偏移量)则执行完整重同步
  • +CONTINUE:执行部分重同步
  • +ERR 主服务器无法识别

心跳检测

REPLCONF ACK (replication-offset)每秒一次
min-slaves-to-write: x
min-slaves-max-lag: y
从服务器少于x个,或者x个从服务器延迟大于等于y秒,主服务器拒绝执行写命令。

SENTINEL模式

SENTINEL是redis的一个特殊模式,SENTINEL系统可以监视任意多个主服务器,以及这些主服务器下的从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器升级为新的主服务器,然后由新的主服务器替代下线的主服务器继续处理命令请求。

启动SENTINEL:
redis-sentinel /path/sentinel.conf
redis-server /path/sentinel.conf --sentinel

对于每个被sentinel监视的主服务器,sentinel会创建两个连向主服务器的异步网络连接:一个是命令连接,用于向主服务器发送命令,另一个是订阅连接:这个连接专门用于订阅主服务器的_sentinel_:hello频道。

SENTINEL默认会以每十秒一次的频率,通过命令连接向被监视的主服务器发送INFO命令,并通过分析INFO命令的回复来获取主服务器的当前信息,包括主服务器本身的信息和主服务器属下的所有从服务器的信息,SENTINEL也会创建连接到从服务器的命令连接和订阅连接。

对于每个与SENTINEL连接的服务器,SENTINEL既通过命令连接向服务器的_sentinel_:hello频道发送信息,又通过订阅连接从服务器的_sentinel_:hello频道接收信息。

SENTINEL之间不会创建订阅连接

实例下线

SENTINEL会以每秒一次的频率向所有与它创建了命令连接的实例发送PING命令,如果一个实例在down-after-miliseconds毫秒内,连接向SENTINEL返回无效回复,那么SENTINEL会修改这个实例所对应的实例结构,在结构flags属性打开SRI_S_SOWN标识。然后SENTINEL回向其他SENTINEL发送命令SENTINEL is-master-down-by-addr 询问其他SENTINEL是否同意主服务器下线,该命令返回SENTINEL is-master-down-by ,当达到一定数量(quorum)已下线判之后,SENTINEL就会将其视为已下线,并选举领头SENTINEL执行故障转移操作。

选举领头SENTINEL(Raft算法)

  1. 先到先得选举局部领头SENTINEL:向其他SENTINEL发送SENTINEL is-master-down-by-addr命令,每次选举SENTINEL的epoch自增一次。
  2. 如果某个SENTINEL被半数以上SENTINEL设置为局部领头,那么这个局部领头SENTINEL就会被设置为领头SENTINEL
  3. 给定时限内为选出,则一段时间之后再次选举,直到选出为止。

故障转移

  1. 选出新的主服务器:挑选出一个状态良好,数据完备的从服务器,然后向这个服务器发送SLAVEOF no one命令,将这个从服务器转换为主服务器。
    选举从服务器策略:
    1) 将从服务器保存到一个列表里面,删除处于下线状态或断线状态的从服务器,删除列表中所有最近5秒内没有回复过领头SENTINEL的INFO命令的从服务器,删除所有与已下线主服务器连接断开超过down-after-milliseconds * 10毫秒的从服务器。
    2)从列表中选举优先级最高的从服务器,有多个优先级最高的从服务器,选举偏移量最大的从服务器,有多个偏移量最大的从服务器,选举运行ID最小的从服务器。
  2. 修改从服务器的复制目标
  3. 将旧的主服务器变为从服务器

集群

向一个节点node发送CLUSTER MEET命令,可以让node节点与ip和port所指定的节点进行握手,当握手成功时,node节点就会将ip和port所指定的节点添加到node节点所在的集群中。节点只能使用0号数据库。Redis服务器在启动时会根据cluster-enabled配置是否为yes来决定是否开启服务器的集群模式。

集群模式下:
1)节点会继续使用文件事件处理器来处理命令请求和返回命令回复。
2)节点会继续使用时间事件处理器来执行serverCron函数,而serverCron函数会调用集群模式下特有的clusterCron函数执行集群模式下的常规操作(如向其他节点发送Gossip消息,检查节点是否下线,或者检查是否需要对下线节点进行自动故障转移)。
3)使用数据库保存键值对,继续使用RDB和AOF,继续使用订阅和发布模块执行PUBLISH和SUBSCRIBE
4)继续使用redisServer保存服务器状态,使用redisClient保存客户端状态,集群模式下的数据保存在cluster.h/clusterNode、cluster.h/clusterLink以及cluster.h/clusterState结构中。

集群的结构

clusterNode结构保存了一个节点的当前状态,比如节点的创建时间,节点的名字,节点当前的配置纪元,节点的IP端口,每个节点都会为自己和集群中所有其他节点创建一个相应的clusterNode结构。
clusterNode结构的link属性是一个clusterLink结构,该结构保存了连接节点所需的有关信息,比如套接字描述符,输入缓冲区和输出缓冲区。
每一个节点都保存着一个clusterState结构,这个结构记录了在当前节点的视角下,集群所处的状态,节点会使用clusterState的slots_to_keys保存槽和键之间的关系。

CLUSTER MEET实现

1)节点A为节点B创建一个clusterNode结构,并添加到clusterState.nodes中
2)节点A对节点B发送一条MEET消息
3)节点B为节点A创建一个clusterNode结构并添加自己的clusterState的nodes中,并向A返回一条PONG消息。
4)节点A接收到PONG消息之后,向节点B返回一条PING消息,握手完成
5)节点A通过Gossip协议将节点B的信息传播给集群中的其他节点

分片

Redis集群通过分片的方式保存数据库中的键值对;集群的整个数据库被分为16384个槽,数据库的键属于这16384个槽中的一个,通过向节点发送CLUSTER ADDSLOTS [slot…]将一个或多个槽指派给其他节点负责。当16384个槽都有节点在处理时,集群处于上线状态(ok),否则处于下线状态(fail)。clusterNode的slots属性和numslot记录了节点负责处理哪些槽。slots属性是一个二进制位数组,长度为16384 / 8 = 2048个字节。如果在索引i上的二进制位为1,表示当前节点负责处理槽i,否则不处理,numslots记录节点负责处理槽的数量。

节点还会将自己的slots数组通过消息发送给集群中的其他节点,接收到消息的节点会将消息保存到相应节点的clusterNode结构里面,clusterState的slots数组记录了集群中所有16384个槽的指派信息。

客户端向集群中的节点发送数据命令时,如果键所在的槽正好指派给了当前节点,那么节点直接执行命令,如果没有指派给当前节点,那么节点会向客户端返会一个MOVED错误,并再次发送之前执行的命令,这是隐式执行的。

重新分片

将任意数量的已经指派给某个节点的槽改为指派给另一个节点,并且相关槽所属的键值对也会从源节点被移动目标节点,重新分片可以在线执行。

重新分片原理:
1)redis-trib对目标节点发送CLUSTER SETSLOT IMPORTING ,让目标节点准备好从源节点导入属于槽slot的键值对。
2)redis-trib对源节点发送CLUSTER SETSLOT MIGRATING ,让源节点准备好将属于槽slot的键值对迁移到目标节点。
3)redis-trib向源节点发送CLUSTER GETKEYSINSLOT 命令,获得最多count个属于槽slot的键值对的键名。
4)对于每个键名,redis-trib向源节点发送一个MIGRATE 0 命令,将选中的键原子地从源节点迁移到目标节点。
5)重复3)和4)
6)redis-trib向集群中地任意一个节点发送CLUSTER SETSLOT NODE 命令,将槽slot指派给目标节点这一指派信息会通过消息发送给整个集群。

  • CLUSTER SETSLOT IMPORTING:将目标节点地clusterState.importing_slots_from[i]的值设置为source_id所代表节点的clusterNode结构。
  • CLUSTER SETSLOT MIGRATING:将源节点的clusterState.migrating_slots_ro[i]的值设置为target_id所代表节点的clusterNode结构。

ASK错误:如果客户端向源节点发送了一个键key的命令请求,如果未找到该key,那么节点会检查自己的clusterState.migraing_slots_to[i],看键key所属的槽i是否正在迁移,如果正在迁移,那么节点会向客户端发送一个ASK错误,接收到ASK错误的客户端会根据错误提供的ip地址和端口号,转向正在导入槽的目标节点,然后向目标节点发送一个ASKING命令(ASKING命令的作用是打开发送该命令的客户端的REDIS_ASKING标识,允许当前节点破例执行这个槽i的命令一次),之后在重新发送原本想要执行的命令。

集群中的主从模式

Redis集群中的节点分为主节点和从节点,主节点用于处理槽,从节点则用于复制某个主节点,当被复制的主节点下线时,某个从节点代替下线的主节点继续处理命令请求。

设置从节点

CLUSTER REPLICATE
1)接收到该命令的节点会将自己的clusterState.myself.slaveof指针指向node_id所对应的节点的clusterNode,并修改自己在clusterState.myself.flags,打开REDIS_NODE_SLAVE。
2)调用复制代码,复制主节点。

监听和故障转移

集群中的每个节点都会定期向集群中的其他节点发送PING消息,以此检测对方是否在线,如果目标节点没有在规定时间内向源节点返回PONG消息,源节点会将目标节点标记为疑似下线。如果在一个集群里面,半数以上负责处理槽的主节点都将某个主节点x报告为疑似下线,那么这个主节点x将被标记为已下线,将主节点x标记为已下线的节点会像集群广播一条关于主节点x的FAIL消息,所有收到FAIL消息的节点都会立即将主节点x标记为已下线。

故障转移:
1)复制下线节点的所有从节点中,选举出一个从节点(Raft算法)
2)被选中的从节点执行SLAVEOF no one命令,成为新的主节点
3)新的主节点会撤销所有对已下线主节点的槽指派,并将这些槽指派给自己
4)新的主节点向集群广播一条PONG消息
5)新的主节点开始接收和自己负责的槽有关的命令请求

通信

集群中的系欸但通过发送和接收消息来进行通信,常见的消息包括MEET、PING、PONG、PUBLISH,FAIL。

Redis常用功能

事务

Redis通过MULTI、EXEC、WATCH命令实现事务。

  • MULTI:开启事务,打开flags属性中的REDIS_MULTI标识
  • EXEC:提交事务,如果执行了WATCH命令,且在EXEC执行之前有其他客户端修改了事务的下的键,则提交失败
  • WATCH:监听事务运行中是否有键改变,有则提交失败

慢查询日志

showlog-log-slower-than:运行时长超过多少微秒会被记录到日志。
showlog-max-len:最多保存多少条慢查询日志

SLOWLOG GET :查看慢查询日志

监听器

MONITOR:将客户端变为一个监视器,打开客户端的REDIS_MONITOR标识,别监视的服务器运行的命令会打印在监视器中。

你可能感兴趣的:(笔记,redis)