zoukankan      html  css  js  c++  java
  • 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事务提供了一种将多个命令打包,然后一次性、顺序性的执行多个命令的机制,并且在执行事务期间,服务器不会中断事务而去执行其他客户端的命令请求,它会在事务执行完后在去执行其他命令

                 

  • 相关阅读:
    推荐下自己的开源框架:DataMapFramework
    真的能无师自通吗?JAVA学习指导系列
    再回首,工作的第一个十年
    2个DataSet中的数据传递问题,请高手们多多指教。
    数据结构小结
    CDQZ_Training 2012524 词编码
    PowerDesigner显示Comment注释
    DDD基本元素
    使用FluorineFx.NET更新FMS中的SharedObject
    如何取消页面缓存
  • 原文地址:https://www.cnblogs.com/carblack/p/12741613.html
Copyright © 2011-2022 走看看