Redis小记(三)

1、复制

通过slaveof命令或设置slaveof选项,实现一个服务器去复制另一个服务器,被复制的是主服务器,执行复制的是从服务器,复制过程中主从双方数据库保持数据一致

2.8版本以前,可分为初次复制和断线重复制两种情况,断线之后从服务器会向主服务器发送SYNC命令,主服务器收到SYNC命令之后执行BGSAVE命令,创建一个从开始到断线期间的RDB文件,并使用缓冲区记录接下来所执行的命令,并将RDB文件发送给从服务器,从武器进行数据同步,但是这样会占据大量的CPU资源、I/O资源、内存资源以及网络资源

2.8版本以后,使用PSYNC命令代替SYNC命令来执行复制时的同步操作,PSYNC命令分为完整重同步和部分重同步两种,完整重同步用于初次复制,部分重同步用于断线重复制,从服务器断线再连接会向主服务器发送PSYNC命令,主服务器收到PSYNC命令命令后会向从服务器返回+CONTINUE命令,执行部分重同步,把断线期间执行的命令发送给从服务器,从服务器执行命令后完成与主服务器数据同步

部分同步同过复制偏移量、复制积压缓冲区、服务器运行ID三部分来实现

复制的过程:客户端向服务器发送SLAVEOF <ip> <port> 命令,设置主服务器的地址端口

      从服务器根据命令中的IP和端口,创建向主服务器的套字连接

      当从服务器成为主服务器的客户端后,向服务器发送一个ping命令,ping用于检查通讯是否正常,主服务是否可以正常处理命令,主服务器会返回一个PONG

      从服务器收到主服务器返回的PONG后,进行身份验证

      通过验证后,向主服务器发送从服务器的监听端口号

      从服务器向主服务器发送PSYNC命令开始同步

      同步之后,主从服务器就会进入命令传播阶段,这阶段主服务器会一直把自己执行的命令发送给从服务器,从服务接收并执行,以达到数据同步的期望

      命令传播阶段,从服务器会每隔1秒向主服务器发送心跳检测命令

2、Sentinel(哨兵)

Redis高可用性解决方案之一,由一个或多个Sentinel实例组成的Sentinel系统可以随意监视多个主服务器以及其下的从服务器

通过$ redis-server /path/to/your/sentinel.conf --sentinel来启动Sentinel

启动Sentinel的步骤:初始化服务器、将普通服务器使用的代码替换为Sentinel专用服务器、初始化Sentinel状态、根据给定的配置文件,初始化Sentinel的监视服务器列表、创建向主服务器的连接(命令连接,向主服务器发送命令和接收命令回复、订阅链接,订阅主服务器的_Sentinel_:hello频道)

Sentinel会默认10秒一次向服务器发送INFO命令并通过解析回复命令获取当前服务器的信息

故障转移:在已经下线的主服务器属下的从服务器中挑选出一个,作为新的主服务器

     让其他从服务器改为复制新主服务器

     将已下线的主服务器设置为新主服务器的从服务器

挑选新主服务器的步骤:将所有从服务器保存到列表里,方便过滤

           删除下线和断线的从服务器

             删除最近5秒内没有回复过Sentinel的INFO命令的从服务器

             删除与已下线主服务器连接断开超过down-after-milliseconds*10毫秒的从服务器

             根据优先级选出剩下从服务器优先级最高的从服务器作为主服务器

3、集群

Redis集群是分布式数据库,集群通过分片(sharding)进行数据共享、复制以及故障转移

一个集群由多个节点组成,在集群中,一个节点就是一个redis服务器,每个节点相互连接,携手工作,可以用命令CLUSTER MEET <ip> <port> 来完成节点连接,某一节点发送CLUSTER MEET命令时,会与ip和port指定的节点进行握手,握手成功,ip和port指定的节点就会添加到这个节点的集群中

Redis服务启动时会根据cluster-enabled的配置来决定是否开启服务器集群模式,集群模式下可以使用单机模式的所有服务器组件

集群模式下使用到的数据会保存到clusterNode结构中,主要保存节点的创建时间、节点名字、当前的配置纪元、ip、端口、连接节点所需要的相关信息等,连接节点所需要的相关信息的link属性是一个clusterNode结构,保存了套接字描述字符、输入缓冲区、输出缓冲区

集群中每个节点都包含一个clusterNode,记录集群现在状态、包含多个节点、集群当前配置纪元信息等

 

 

 CLUSTER MEET <ip> <port> 命令实现:客户端向A节点发送CLUSTER MEET <ip> <port> 命令,A节点会把指定IP、端口的B节点添加到A所在的集群里

                    A节点收到命令后,与B节点进行握手,确认B节点是否存在,此时A节点会为B节点创建一个clusterNode,并把这个clusterNode添加到自己的clusterStater.nades字典里,之后,A节点会向B节点发送一条MEET消息

                    B节点收到A节点发送的消息,为A节点创建一个clusterNode,并把这个clusterNode添加到自己的clusterStater.nades字典里,并向A节点返回一条PONG消息

                    A节点收到PONG消息后向B节点发送一条ping消息,此时A已知与B已经连通

                    B节点收到ping消息,此时B已知与A已经连通,握手完成

                    A节点会将B节点的信息通过Gossip协议传播给集群中其他节点,其他节点相继与B节点进行握手,全部完毕后,B节点加入集群

槽指派:redis集群通过分片来保存数据库中键值对,集群中数据库被分为16384个槽,数据库中每个数据都属于这个槽的其中一个,每个节点可以处理0到16384个槽

当集群中16384个槽都有节点处理时,集群处于上线状态,反之处于下线状态,通过CLUSTER ADDSLOTS命令可以把把一个或多个槽指派给节点

节点会把自己负责处理的槽记录到clusterNode中的slots(数组结构,记录处理哪些槽)属性和numslotss属性(记录处理槽的数量),还会把自己的slots(数组结构,包含16384个项,记录处理哪些槽)属性通过消息群发给集群中其他节点

集群模式下,当所有节点都加入到集群中并给每个节点都指派槽之后,集群正式上线,当客户端向节点发送处理数据的命令时,接收的节点会计算出命令要处理的数据属于哪个槽,并检查这个槽是否分配给自己,是,直接处理,否,向客户端返回一个MOVED的错误(MOVED错误是会隐藏的,不会打印出来),并指引客户端指向正确的节点,再次发送命令

集群数据库与单机数据库对键值对过期处理是一样的,但是集群数据库只能使用0号数据库

重新分片:集群中重新分片可以把任意数量的槽指派给别的节点,相关槽的键值对也会转移到新节点下,重新分配时,集群不用下线,可以继续处理数据

ASk错误:重新分片期间,客户端向A节点发送一条数据处理的命令,而此时A节点中这条数据已经转移到B节点,A节点会向客户端返回一个ASK错误,并指引客户端指向B节点

复制和故障转移:集群中节点分为主节点和从节点,主节点负责处理槽,从节点负责复制主节点和主节点下线时代替主节点继续处理命令,每个节点之间定期向其他节点发送ping命令并查看在规定时间内是否收到pong命令,以此来检测故障

故障转印步骤:在从节点中选出一个执行SLAVEOF NO ONE命令,提升为新的主节点

          新的主节点会撤销所有对已下线主节点的槽的指派,并将这些槽都只派给自己

       新的主节点向集群广播一条pong消息,这条pong消息会让其他节点知道主节点已经变更,新主节点负责处理原主节点所指派的槽

       新节点开始接收和处理自己负责的槽的命令,故障转移完成

集群中节点发送消息类型:MEET消息,节点加入集群中时发送

            PING消息,每个节点定期发送

            PONG消息,回复MEET消息和PING消息

            FALL消息,当A节点判断B节点进入FALL状态,会向集群中广播B节点进入FALL状态

            PUBLISH消息,当一个节点收到PUBLISH命令时,节点会执行命令,并向集群广播这条命令

4、发布和订阅

redis中发布和订阅是通过PUBLISH、SUBSCRIBE、PSUBSCRIRE等命令组成

redis把所有的订阅关系都保存在服务器状态的pubsub_channels字典里,字典中键是被订阅的频道,键的值是一个链表,记录所有订阅频道的客户端

redis把所有的订阅关系都保存在服务器状态的pubsub_patterns的链表里,链表中每个节点都包含一个PubsubPatterns结构,PubsubPatterns中pattern属性记录被订阅的模式,client属性记录订阅这个模式的客户端

SUBSCRIBE:客户端通过此命令订阅一或多个频道,成为频道的订阅者,每当其他客户端向频道发送消息时,频道所有的订阅者都可以收到这条消息

UNSUBSCRIBE:退订频道,根据退订频道的名字在pubsub_channels字典中找到相应的订阅的信息,从链表中删除退订客户端信息,当客户端信息为0时,删除频道对应的键

PSUBSCRIBE:客户端通过此命令订阅一或多个模式,成为模式的订阅者,每当其他客户端向频道发送消息时,不仅频道所有的订阅者都可以收到这条消息,与这个频道相匹配的模式的订阅者也会收到

PUNSUBSCRIBE:退订模式,服务器在pubsub_patterns链表中查找并删除那些pattern属性为被退订模式,并且client属性为执行退订命令客户端的pubsubPattern结构

PUBLISH <channel> <meaasge>:将消息message发送给channel频道,频道的所有订阅者和与channel频道模式相匹配的模式的订阅者也会收到

查看订阅消息:PUBSUB CHANNELS,用于返回服务器当前被订阅的频道

       PUBSUB NUMSUB,返回频道的订阅者数量

         PUBSUB NUMPAT,返回服务器当前被订阅模式数量

5、事务

redis事务提供了一种将多个命令打包,然后一次性、顺序性的执行多个命令的机制,并且在执行事务期间,服务器不会中断事务而去执行其他客户端的命令请求,它会在事务执行完后在去执行其他命令

 

 

 

             

 

posted @ 2020-04-21 21:33  CarBlack  阅读(126)  评论(0编辑  收藏  举报