范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

浅谈集群的分类

  本文主要介绍集群部署相关的知识,介绍集群部署的基础,集群的分类、集群的负载均衡技术,集群的可用性以及集群的容错机制。随后介绍Redis-Cluster以及Mysql的架构以及主从复制原理。
  单台服务器本身会受到带宽、内存、处理器等多方面因素的影响,当通过垂直扩展已经无法提升系统性能时,我们就需要通过水平扩展,即以集群的方 式来部署服务。集群在提升性能的同时,也可以 减轻单机器的压力,提高系统的可用性。这就是我们常说的加机器,简单粗暴,但非常有效。
  提到集群,一定会想到分布式,不过要注意这两者的区别。集群强调的是服务的多个副本冗余部署;分布式强调的是将整个系统拆分成多个子系统独立开发、维护和运行,每个子系统仍然以集群的方式部署。Redis-Cluster就是典型的分布式系统,每个节点采用一主多从的集群方式部署。
  Redis-Cliuster架构图
  对于集群的分类,网上说最多的就是分成高性能集群、高可用集群、负载均衡集群,但我却不敢苟同。我认为三者之间是分不开的,你中有我,我中有你,比如通过负载均衡就可以实现高性能、高可用,或者说负载均衡是手段,高性能高可用是结果。所以我更倾向于将集群分成两种:即无状态服务的水平扩展集群和有状态的主从集群。
  无状态服务的水平扩展集群
  该方式实现的前提是服务本身是无状态的,举例来说,如果服务是一个Web应用,访问界面需要用户登录态,如果session是保留在本地服务器上,那么这个服务就是有状态的。如果用户的多次请求打到了不同的机器上,就会出现重复登录的问题。但如果session存储在中间件中,比如Redis,那么就是无状态的。
  通过机器的水平扩容,就构建了服务的集群,随后通过负载均衡的算法,将请求分散到不同的机器上。
  负载均衡几个比较重要的指标:负载均衡算法、容错机制以及健康检测。负载均衡算法
  1、随机算法
  思想:服务集群中的每个服务都配置一个权重weight,默认是100。如果所有权重相等,则随机选择一个;如果权重不等,即为加权随机算法。比如现在有两个服务A,B,权重分别是100,200,那么选取比例就是 1/3,2/3。
  Dubbo实现算法: @Override     protected  Invoker doSelect(List> invokers, URL url, Invocation invocation) {         // Number of invokers         int length = invokers.size();         // Every invoker has the same weight?         boolean sameWeight = true;         // the weight of every invokers         int[] weights = new int[length];         // the first invoker"s weight         int firstWeight = getWeight(invokers.get(0), invocation);         weights[0] = firstWeight;         // The sum of weights         int totalWeight = firstWeight;         for (int i = 1; i < length; i++) {             int weight = getWeight(invokers.get(i), invocation);             // save for later use             weights[i] = weight;             // Sum             totalWeight += weight;             if (sameWeight && weight != firstWeight) {                 sameWeight = false;             }         }         if (totalWeight > 0 && !sameWeight) {           随机选取小于总权重的整数             int offset = ThreadLocalRandom.current().nextInt(totalWeight);             //这个是关键,如果减去总权重是负数,即为选中的Invoker             for (int i = 0; i < length; i++) {                 offset -= weights[i];                 if (offset < 0) {                     return invokers.get(i);                 }             }         }       //完全随机         return invokers.get(ThreadLocalRandom.current().nextInt(length));     }
  2、RoundRobin轮询
  最简单的轮询就是依次轮询,比如有N台服务器,编号从0到N-1依次轮询执行,没有任何的复杂算法。
  下面是一个简单的实现:  public class RoundRobinBalance {      public static final List selectList = Lists.newArrayList(1,2,3);      private int getWeight(Integer integer){         return integer;     }      private AtomicInteger atomicInteger = new AtomicInteger(-1);      public int simpleRoundRobin(){         int index = atomicInteger.addAndGet(1);         int length = selectList.size();         if (index >= length){            index = atomicInteger.addAndGet(-length);         }         return selectList.get(index);     }  }
  但实际中,每台服务器可能配置不同,我们需要为不同的服务器增加不同的权重,部分服务器需要大概率被选中,权重就设置大一些,否则就设置小一些。带权重的轮询俗称WRR算法。
  WRR目前有两种实现方式,一种是Nginx实现的平滑最大权重,dubbo也是参考这种模式。二是LVS实现的算法,其优先选择权重最大的服务器。
  Nginx & Dubbo:不同权重的服务器,每次选择权重最大的,选中后,该权重会减去总权重,随后会加上其初始值。
  类似下面的过程: In case of { 5, 1, 1 } weights this gives the following sequence of current_weight"s:       a  b  c      0  0  0  (initial state)       5  1  1  (a selected)     -2  1  1       3  2  2  (a selected)     -4  2  2       1  3  3  (b selected)      1 -4  3       6 -3  4  (a selected)     -1 -3  4       4 -2  5  (c selected)      4 -2 -2       9 -1 -1  (a selected)      2 -1 -1       7  0  0  (a selected)      0  0  0
  看一下dubbo的实现: public class RoundRobinLoadBalance extends AbstractLoadBalance {     public static final String NAME = "roundrobin";          @Override     protected  Invoker doSelect(List> invokers, URL url, Invocation invocation) {         String key = invokers.get(0).getUrl().getServiceKey() + "." + invocation.getMethodName();         ConcurrentMap map = methodWeightMap.get(key);         if (map == null) {             methodWeightMap.putIfAbsent(key, new ConcurrentHashMap());             map = methodWeightMap.get(key);         }         int totalWeight = 0;         long maxCurrent = Long.MIN_VALUE;         long now = System.currentTimeMillis();         Invoker selectedInvoker = null;         WeightedRoundRobin selectedWRR = null;         //找出当前权重最大的,并计算总权重。         for (Invoker invoker : invokers) {             String identifyString = invoker.getUrl().toIdentityString();             WeightedRoundRobin weightedRoundRobin = map.get(identifyString);             int weight = getWeight(invoker, invocation);             long cur = weightedRoundRobin.increaseCurrent();             weightedRoundRobin.setLastUpdate(now);             //找出权重最大的             if (cur > maxCurrent) {                 maxCurrent = cur;                 selectedInvoker = invoker;                 selectedWRR = weightedRoundRobin;             }             totalWeight += weight;         }                 }         if (selectedInvoker != null) {             //对于选中的,会对其权重进行抵减,值为totalWeight。             selectedWRR.sel(totalWeight);             return selectedInvoker;         }     }  }
  LVS的加权轮询每次都会选择权重最大的,的wiki说明: Supposing that there is a server set S = {S0, S1, …, Sn-1}; W(Si) indicates the weight of Si; i indicates the server selected last time, and i is initialized with -1; cw is the current weight in scheduling, and cw is initialized with zero;  max(S) is the maximum weight of all the servers in S; gcd(S) is the greatest common pisor of all server weights in S;  while (true) {     i = (i + 1) mod n;     if (i == 0) {         cw = cw - gcd(S);          if (cw <= 0) {             cw = max(S);             if (cw == 0)             return NULL;         }     }      if (W(Si) >= cw)          return Si; }
  Python版的实现: class Store:     __slots__ = ("index", "weight")      def __init__(self, index, weight):         self.index = index         self.weight = weight   def weighted(dataset):     current = Store(index=-1, weight=0)      dataset_length = len(dataset)     dataset_max_weight = 0     dataset_gcd_weight = 0      for _, weight in dataset:         if dataset_max_weight < weight:             dataset_max_weight = weight         dataset_gcd_weight = gcd(dataset_gcd_weight, weight)      def get_next():         while True:             current.index = (current.index + 1) % dataset_length             if current.index == 0:                 current.weight = current.weight - dataset_gcd_weight                 if current.weight <= 0:                     current.weight = dataset_max_weight                     if current.weight == 0:                         return None             if dataset[current.index][1] >= current.weight:                 return dataset[current.index][0]      return get_next
  3、最少连接数均衡(Least Connection)
  思想:对每一台服务器都会记录当前正在处理的连接数量,当有新的服务连接请求时,将把当前请求分配给连接数最少的服务器。如果有多台服务器都满足最小连接数,就变成随机算法。此种均衡算法适合长时间处理的请求服务。感兴趣的可以看下Dubbo的实现: LeastActiveLoadBalance。
  4、处理能力均衡
  思想:把服务请求分配当前系统负载最小的服务器,由于考虑到了内部服务器的处理能力及当前网络运行状况,所以此种均衡算法相对来说更加精确。
  5、目标地址散列:
  思想:根据请求的目标IP地址,作为散列键(Hash Key)从散列表找出对应的服务器。
  6、源地址散列:
  思想:根据请求的源IP地址,作为散列键(Hash Key)散列表找出对应的服务器。
  7、一致性Hash
  相比较普通hash算法,一致性hash算法在扩缩容时,影响的数据范围比较小,方便客户端做路由缓存。针对该算法,在之前写的文章小米分库分表的实践 中有过介绍。在使用时为了避免数据倾斜,如果服务器数量较少的情况,要使用虚拟节点。Dubbo的实现方式是默认增加160个虚拟节点。并对每个ip+port后增加数字 1,2,3..... 。一致性Hash的存储结构最好的是使用红黑树TreeMap,因为其实现完美满足一致性hash算法。
  容错机制
  dubbo客户端通过watch注册中心的节点实现动态变化,此外支持不同方式的集群容错:
  1)failover
  失败自动切换,自动重试其他机器,常用于  读  操作。注意这里强调的是读请求,对于写请求,最好不要使用该模式。举例,如果某个接口是扣减金额接口,因为出现死锁或其他问题,导致接口超时了,此时会继续调用其他的服务器,这就导致接口被调用了两次或者多次。如果接口没有设计幂等(哪位大牛会不考虑幂等呢),那问题就比较严重了。
  (2)failfast
  快速失败,一次调用失败就立即失败,常用于非幂等的  写  操作或者是对时延要求较高的场景。
  (3)failsafe
  调用异常时忽略异常,不报错。该模式多用于一些不是特别重要的接口调用,比如邮件通知、数据统计等等。
  (4)failback
  失败后自动记录请求,然后定时重发,比较适合于一些异步操作,比如发送消息。
  (5)forking
  并行调用多个provider,只要一个成功就立即返回。常用于实时性要求比较高的读操作,但是会浪费更多的服务资源,可通过forks="2"来设置最大的并行数
  (6)broadcacst
  逐个调用所有的provider,任何一个provider出错则报错。常用于通知所有提供者更新缓存或日志等本地资源信息。
  健康检测
  对于负载均衡的服务器,应该具备某种健康检测机制,确保如果某个服务器异常下线,需要将其从负载均衡列表中摘除。健康检测可以是被动检测,也可以是主动检测。
  被动检测思想类似于熔断,当多次调用超时或者失败,会在一定时间内不再访问对应服务器。下面是参考资料中的一个示意图,阐述得比较清晰。
  被动检测的最大问题就是对于异常的机器不能及时摘除,导致仍然会有请求分发到异常机器上。因此
  如Dubbo+nacos实现的负载均衡,nacos通过和客户端和服务端建立连接,每几秒都会检测目标机器是否异常,如果异常会从当前注册列表中摘除。不过在实际使用中要注意,摘除异常并不是实时的,是定时发生的,也就是说存在客户端依然会调用异常Ip的可能。
  负载均衡分类
  目前负载均衡的实现有很多种,从TCP/IP协议栈的角度划分,包括四层负载均衡、七层负载均衡。
  四层负载均衡:即在传输层实现的负载均衡,如LVS,Nginx都支持四层负载均衡。
  七层负载均衡:即在应用层实现的负载均衡,如HTTP协议、DNS协议等,HTTP协议实现的负载均衡如Nginx,Dubbo等。
  从软硬件角度可划分出DNS负载均衡、软件负载均衡、硬件负载均衡。
  硬件负载均衡需要购买专门的硬件产品实现,而且都很昂贵,基本上是淘汰的,过时的。
  软件负载均衡是通过软件来实现的,价格比较便宜,性能也比较优越。如nginx,lvs都是优秀的负载均衡软件。
  在实际应用中,通常情况会结合着使用不同的负载均衡技术。如下图所示:
  七层负载均衡:Nginx HTTP协议DNS DNS协议Dubbo HTTP协议
  四层负载均衡:
  Nginx
  LVS
  Nginx负载均衡
  nginx支持七层和四层负载均衡两种,不过四层负载均衡需要第三方插件的支持。
  Nginx七层负载均衡的配置非常简单。 upstream account_backend {     server 127.0.0.1:9090 max_fails=3 fail_timeout=10s weight=2;     server 127.0.0.2:9090 max_fails=3 fail_timeout=10s;     server 127.0.0.3:9090 max_fails=3 fail_timeout=10s;  }
  当请求过来时,会根据某种算法选择某一个ip进行访问。Nginx默认使用加权轮询,权重默认是1。此外,Nginx还内置了ip hash算法,通过对客户端ip进行hash选择一个服务器,通过该方法可保证同一用户的可只打到一个后端机器上。 upstream account_backend {    ip_hash;     server 127.0.0.1:9090 max_fails=3 fail_timeout=10s ;     server 127.0.0.2:9090 max_fails=3 fail_timeout=10s;     server 127.0.0.3:9090 max_fails=3 fail_timeout=10s;  }
  当后端服务器集群中某个挂掉了,Nginx会自动将请求转到其他节点上。但是它默认不会将该异常节点摘除,后续的请求还是可能打到异常机器上的。至于这点,可以看这篇文章,该文章详细介绍了该如何进行后端健康检测的: Nginx负载均衡中后端节点服务器健康检查 - 运维笔记 - 散尽浮华 - 博客园,主要介绍了淘宝团队开发的nginx继承模块,通过主动检测实现自动剔除异常的server。
  DNS负载均衡
  DNS负载均衡实现的是广域网的全局负载均衡,通过为域名配置不同的A记录,实现将请求按照权重分散到不同的ip。这里的ip并不一定是实际的服务器ip,可以是nginx集群,也可以是lvs的vip。
  下面是腾讯云DNSPod的一个实操:
  优点 近乎零成本,因为域名注册商的这种解析都是免费的; 部署方便,除了网络拓扑的简单扩增,加服务器只需要在配置里加上相应ip。
  缺点 健康检查,如果某台服务器宕机,DNS服务器是无法知晓的,仍旧会将访问分配到此服务器。修改DNS记录全部生效时间需要很久。 缓存问题。一般低级DNS都会缓存域名IP映射关系,如果某个出现问题或者发生变化,不会及时更新。
  不知道大家听说过2009年的暴风影音事件,因为两家游戏公司恶意竞争,一个公司恶意攻击另外一家公司网站,导致DnsPod服务器受到Ddos攻击,再加上当时著名的暴风影音使用了免费的DnsPod服务器,也受到了影响,那时的暴风今非昔比,用户量巨大,导致大量域名解析请求达到了电信的DNS服务器,占用了典型机房的1/3的带宽,于是乎,被电信封掉了ip。这一封不要紧,直接导致使用DnsPod解析的网站全部无法访问,数量达到10万+。有感兴趣的可以看看历史回顾,很精彩,DnsPod创始人很厉害,叫吴洪声,作为一个大专生,靠着爱好和坚持搭建了DnsPod,现在已经被腾讯收购了,妥妥的人生赢家。
  LVS负载均衡
  四层负载均衡是针对七层负载均衡的一个补充,当Nginx的并发超过上线时,就需要通过LVS+Nginx集群实现高并发。
  主要模式主要有以下几种: LVS-NAT 主要通过网络地址转换,修改目的IP实现。Network Address Translation LVS-TUN 主要封装一层IP头 IP Tunneling LVS-DR 主要是修改目的MAC Direct Routing LVS-FULLNAT 这个是阿里研发的一种模式,主要是解决多vlan的场景,它会修改请求报文的(源/目的)地址、(源/目的)端口。
  先看几个LVS的名词定义: CIP:客户端ip
  Director:负载调度集群的主机,简称DR
  VIP:Virtual IP,向外提供服务的IP
  RIP:Real Server IP,内部真正提供服务的IP
  DIP:DR主机用于内部通信的IP
  1、LVS-NAT
  流程示意图:
  其请求处理流程:
  1.客户端发送请求到LVS, 目标IP地址为VIP
  2. LVS根据某种负载均衡算法选择一个Real-server,并记录连接信息到hash表中,然后修改客户端的request的目的IP地址为选择的RS(这个RIP只是内部通信用的),随后将请求发给RS,此时源IP为CIP,目的IP为RIP;
  3. RS收到request包后,发现目的IP是自己的IP,于是处理请求,然后发送reply给LVS,此时源IP为RIP,目的IP是CIP;
  4. LVS收到reply包后,修改reply包的的源地址为VIP,原端口为VIP端口;
  5. LVS将reply发送给客户端;
  6. 客户端来的属于本次连接的包,查hash表,然后发给对应的RS;
  7. 客户端发送完毕,此次连接结束时,LVS自动从hash表中删除此条记录;
  上面流程的特点是:
  1、DR和RS必须是在同一个网段内,RS的网关配置成DIP,RIP和DIP都是用于内网机器间通信的IP。我感觉说的直白点,DR就是局域网网关的角色;
  2、所有请求响应都要经过DR,这必然会导致DR会成为整个网络的瓶颈。
  2、LVS-TUN
  1.客户端Client 发送request包到LVS服务器, 目标地址VIP;
  2. LVS按照算法选择后端的一个Real-server,并将记录一条消息到hash表中,然后将客户端的request包封装到一个新的IP包里,新IP包的目的IP是RIP,源IP是DIP,然后转发给RS;
  3. RS收到包后,解封装,取出客户端的request包,发现还有一个IP包,目的地址是VIP,而RS发现在自己的虚拟网卡tunl0上有这个IP地址,于是处理客户端的请求,处理完成通过虚拟网卡发送给eth0网口发送出去,此时源IP为VIP,目的地址是CIP;
  4. 该客户端的后面的request包,LVS直接按照hash表中的记录直接转发给Real-server,当传输完毕或者连接超时,那么将删除hash表中的记录。
  该模式中:
  RIP,VIP,DIP都可以是公网地址,可以跨网段;
  请求报文都走DR,响应不走,直接由RS发送给Client。这个特点使得TUN的性能要相比NAT提升了几倍,且解决了跨网段问题,问题就在于其维护成本挺高的;
  3、LVS-DR
  1、客户端Client 发送request包到LVS服务器, 目标地址VIP;
  2、LVS根据负载均衡算法选择一台Realserver,将此RIP所在网卡的mac地址作为目标mac地址,发送到局域网里,因为是在数据链路层,所以必须在同一局域网;
  3、RS在局域网中收到这个帧,拆开后发现目标IP不是自己的IP,正常来讲RS会抛弃的,但由于我们在loopback接口上配置了VIP,所以RS会接收该请求包并进行处理。
  4、处理后,RS直接经过网络发送给客户端,源IP为VIP,目的IP为CIP。
  LVS-DR技术解决了NAT的DR瓶颈问题,提高性能,但其最大限制就是DR和RIP必须是同一网段的,不能解决跨网段的问题。
  4、LVS-FULLNAT
  这个是阿里做的,LVS的DR和NAT模式要求RS和DR在同一个vlan中,导致部署成本过高;TUN模式虽然可以跨vlan,但RealServer上需要部署ipip隧道模块等,网络拓扑上需要连通外网,较复杂,不易运维。
  为了解决上述问题,开发出FULLNAT,该模式和NAT模式的区别是:数据包进入时,除了做DNAT,还做SNAT(用户ip->内网ip),从而实现LVS-RealServer间可以跨vlan通讯,RealServer只需要连接到内网。
  当客户端访问VIP后,DR会将源IP改成DIP,目的IP改成RIP。剩下的就是内网调用的事情了,可以是同网段,也可以是不同网段,至于不同Vlan如何通信,这个就不多说了,就是路由策略配置的问题了。
  FULLNAT相对于之前那三种方式,配置维护都很简单,可以跨网段。现在也是LVS主流的使用模式。
  LVS本身的部署有以下几种模式:
  1、单机模式,一个LVS对应多个Nginx server;
  2、一主一备+KeepAlived,提高可用性;
  3、集群模式。通过FullNAT+OSPF-ECMP,并使用一致性hash算法实现分流。
  目前最多的就是集群部署方式,其特点为: LVS 和上联的三层交换机间运行 OSPF 协议。 OSPF 开放最短路径优先,是一种常用的路由协议。 上联交换机通过 ECMP 等价路由,将数据流分发给 LVS 集群。ECMP充分应用在各大路由协议中,如OSPF,ISIS、EIGRP、BGP等。它可保证如果存在多条相等路径,会充分利用多条路由,从而实现基于流的负载均衡(如果不开ECMP,那么当选择一条路由后,或许都会一直使用该路由,其他相等路径都不会走)。 LVS 集群再转发给业务服务器。
  目前我们公司的所有服务几乎都用了LVS。即便时我开发的结算系统,虽然是ToB和内部财务使用,也同样用了LVS,用了两台Real Server,1台DIP,利用权重轮询。不过现在还把一台给停了,另外一台权重配置成100%了,哈哈。
  有状态的需要存储数据的主从集群
  有些服务器为了实现高可用性,会冗余部署多台服务器,并设置主从关系。可以是一主多从,也可以是多主多从。对于这种类型的集群部署,重要的是完成数据的复制以及当主服务器down时,可以实现自动或者手动切换,某台slave可以自动切换成主服务器。其中最典型的例子就是Mysql主从以及Redis中的主从部署,本文主要是介绍这两种。
  Mysql高可用架构
  Mysql的高可用架构有很多中,有一主一从,一主多从,双主+KeepAlive等。其中最常用的就是一主多从。通过水平扩展的方式可以实现Mysql数据库的高可用,同时实现流量分摊,并能够在某台master异常时,能够通过一定手段完成切换。
  引入集群的部署模式后,在带来高可用、高性能的同时也引入了新问题,比如如何保证主从数据库的数据一致性、如何解决主从延迟、如何完成流量的切换等问题。
  数据需要从主库同步到从数据库,从而保证数据的一致性,并通过不同的复制模式来实现强一致性、弱一致性、最终一致性等。先看一下Mysql主从复制的流程:主库将数据更改记录到binlog中; 从库开启一个IO线程,并在主库开启一个特殊的binlog dump线程,将binlog数据 拷贝到从库的relay log中;从库并不是不断轮询去做同步操作。而是当主库有数据更改时,会给主库发送一个信号量。主库返回的信息不仅仅有binlog内容,还有新的binlog文件名,它以及下一个更新的binlog文件的位置。 从库使用SQL线程读取relay log中的数据,并将其写入到从库数据表。
  可以看一下slave的processlist: ysql> show processlistG; *************************** 1. row ***************************      Id: 4    User: system user    Host:       db: NULL Command: Connect    Time: 5205   State: Waiting for master to send event    Info: NULL *************************** 2. row ***************************      Id: 5    User: system user    Host:       db: NULL Command: Connect    Time: 5113   State: Slave has read all relay log; waiting for more updates    Info: NULL *************************** 3. row ***************************
  上面就是从库的两个线程,一个IO线程,一个SQL线程。实际上在Mysql5.6之后,SQL线程不仅仅只有一个,可以是多SQL线程并发执行。
  传统的复制是根据文件位置开始进行的,但自从5.6之后引入了一个叫GTID的概念。GTID,global transaction identifieds全局事务标识。这个标识是唯一的,它可保证一个事务只能被执行一次。
  在主从复制过程中,Master在更新数据时会生成一个GTID,并写在binlog中。从库的SQL线程在执行中继日志的过程中,会检查从库的binlog是否已经有了某个GTID记录,如果有就略过,如果没有就执行。
  我们可以查看当前Mysql是否已经开启了GTID。 mysql> show variables like "gtid_mode"; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | gtid_mode     | ON   | +---------------+-------+
  Mysq复制方式主要包括异步复制、同步复制和半同步复制。
  异步复制:当master执行了相应的写操作,执行成功后直接返回客户端。随后异步得将数据同步到slave。这种好处就是在完成复制的同时,不会牺牲系统的响应速率,但最大的问题就是不能保证数据一致性;
  同步复制:当master在执行写操作时,必须要等到所有slave库的relay log写完,才能够返回给客户端。该模式可以较好低保证数据一致性,但却严重影响系统性能,从库越多,性能越差;
  半同步复制:该复制模式是异步方式和同步复制的折中方案,只要slave中有一个成功写入relay log,master就可直接返回,如果在一定时间内,没有slave写入成功,则复制模式变为异步复制。
  Mysql默认是采用异步复制的,可能其更看重的是系统性能,系统崩溃的概率还是比较低的,在实际中,我们可以根据自身使用场景来选择复制模式。
  binlog模式
  目前binlog的记录模式主要有三种,基于语句(statment),基于行(Row)模式,混合(mixed)模式。
  基于语句的模式就是binlog记录的是所有可能影响数据变化的sql语句。然后在从库中再完全相同地执行一遍。这种模式比较好的地方是只记录语句,不用记录每一行的变化,数据量相对不大,节省带宽。比如一条批量update,只需要传一条语句,不用传每个更改的数据。但这种模式的缺点就是虽然主从库执行的sql完全相同。但主从库的上下文环境是不同的,而sql可能是严格依赖于环境的,比如当前时间戳等等。
  基于行的模式,是记录被修改的数据,而不是sql语句。这种模式使得从库并不会因为环境不同,导致数据不能完全一致。但基于行的模式,可能会导致binlog的数据量特别大,就像上面说到的update,可能会在binlog产生更多的数据记录。这给复制造成了更大的开销。
  mix模式,该模式是上述两种模式的组合。Mysql会根据实际的sql来决定选择哪个模式进行写入。
  Redis-Cluster
  Redis的系统架构经过了多次的演进,最开始的架构模式是一主多从,但由于其无法实现故障自动切换,随后增加了sentinel哨兵机制,即在主从的基础上增加一个哨兵进行监控,从而实现master出现故障时可自动切换。
  从上面示意图可以看出,哨兵机制需要额外的机器节点来实现,完全和Redis无关,不存储数据,只用来监控,这在一定程度上造成了资源的浪费。基于此,Redis官方又开发出一套新的Redis架构,即Redis-Cluster,一个纯分布式的系统架构,示意图在文章最开始已经画出来了,这里再粘贴一下。
  多个master节点通过Gossip协议实现元信息的交互和通信,实现命令包括Meet,Ping,Pong,Fail等,本文对此不做过多阐述,只讲述每个master节点和其slave所构成的集群模式。
  Redis-Cluster的master-slave主要有以下几个作用:
  1、保持高可用;
  当某个master节点下线时,会自动切换到某个slave,slave会升级为新的master,从而实现故障的自动切换。具体流程是:
  1、通过Ping消息,master节点在一定的超时时间内没有响应,就被标记为疑似下线,如果有多个节点认为该master节点疑似下线,那么该master就标记为下线。
  2、master下的slave发起选举,其他的master节点会为相应的slave进行投票,根据Raft协议,选择出新的master节点;
  这里要注意两点。一是slave发起选举,二是master投票。
  Slave在认为master进入FAIL之后会delay一段时间才会发起选举,其原因是为了让master的FAIL状态在集群内广播。不同的slave的delay时间是不同的,从而避免一个master的多个slave在同一时间发起election。
  master投票的条件:Slave所属的master的状态为FAILSlave的currentEpoch大于等于master的currentEpochSlave的configEpoch大于等于master认为该slave所属master的configEpochMaster维护一个lastVoteEpoch字段,针对每一个epoch只会投票一次,一旦投票后就会拒绝所有更小的epoch投票就会回复ACK,否则就忽略
  3、slave选举为新的master节点后,会被分配旧master的哈希槽。
  2、实现读写分离;
  Redis-Cluster中的master节点对外提供写服务,slave可以对外提供读服务。
  如果要实现高可用和读写分离,前提是要实现主从复制,即保证主从节点的数据的一致性。Redis的主从复制主要包括两种 全量复制和部分复制。其中全量复制通常发生在第一次同步过程或者在部分复制出现异常时。
  当在slave中使用slaveOf(Redi5.0之后使用replicaof),确定slave和master的关系。  slave of ip  port
  具体复制流程可见下图,来自小林coding:
  1、执行slaveof之后,主从服务器会建立一个长连接。随后从服务器向主服务器发送psync命令(早期版本是syncc),psync命令有两个参数,一个是runid,表示的是主服务器id;一个是offset,表示的是偏移量。第一次执行时,从服务器不知道主服务器的runId,所以参数是"?",且没有读取任何数据,偏移量是-1;
  2、主服务器收到命令后,会开始执行全量复制。首先会执行bgsave命令,生成RDB文件,随后将其发送给从服务器,slave收到RDB文件之后,会载入RDB文件数据。
  3、在上一步执行期间,有可能还会有写命令进入,而这些写命令执行结果并没有在RDB文件中,因此主服务器为了处理这部分数据,在执行间隙会将写命令写入到一个叫做replication buffer缓冲区中。当slave加载完RDB文件之后,主服务器会将缓冲区中的写命令发送给slave,随后slave继续执行这些写命令;
  4、完成第一次全量同步之后,后续只要主服务器有写命令产生,就会将写命令异步地同步给从服务器。
  5、如果某个slave网络断开之后恢复了。从服务器会给master发送psync命令,其中会传入主服务器的runid以及读偏移量。
  6、主服务器会判断从服务器要读取的偏移量数据是否在repl_backlog_buffer中,如果在就执行增量复制;如果不在,则执行全量复制。
  本文主要讲述了两种不同的集群模式,一是无状态的集群;二是有状态,需做数据存储的集群两种。无状态集群介绍了负载均衡分类以及负载均衡算法;有状态集群介绍了主从复制的原理和流程。
  参考资料:
  深入浅出负载均衡 - SegmentFault 思否
  [万字长文] 吃透负载均衡 - 高性能架构探索
  Dubbo 一致性Hash负载均衡实现剖析 | Apache DubboDUBBO LOGO
  Nginx负载均衡(仅学习) - 知乎
  千与千寻-Mysql复制
  详解nginx的原生被动健康检查机制&灾备使用(含测试)_无影V随风的博客-CSDN博客_被动健康检查
  高并发场景 LVS 安装及高可用实现 - 惨绿少年 - 博客园
  Redis哨兵模式(sentinel)学习总结及部署记录(主从复制、读写分离、主从切换) - 散尽浮华 - 博客园
  主从复制是怎么实现的? | 小林coding
  深度探索MySQL主从复制原理 - 知乎

Steam多人在线硬核生存游戏雅戈泰探险今日开启抢先体验摘要今日,多人硬核生存游戏雅戈泰探险在Steam平台开启抢先体验。这款游戏灵感源自全球民间传说与神秘理论,采用第一人称视角与PvPvE中世纪战斗模式,以原创IP带领玩家踏上神话与探大戏看北京第六届老舍戏剧节正式启动,将上演50余场演出新京报讯(记者刘臻)8月18日,大戏看北京2022第六届老舍戏剧节新闻发布会在天桥艺术中心举行,随着俗世奇人安娜卡列尼娜等一系列重磅话剧音乐剧签名开票,大戏看北京2022第六届老舍痘痘肌完全护肤的6个步骤,做好了,皮肤变好不难祛痘关键词清洁保湿抗炎疏通修复防晒。6个护肤要点。如果都做好了,痘痘肌肤会很不一样。清洁1痘痘肌可以使用含有水杨酸,果酸乳酸等等轻微剥脱效果的清洁产品。2如果痘痘肌合并敏感肌,可以斯诺克欧洲大师赛颜丙涛吴宜泽强势晋级,赵心童憾负新华社柏林8月18日电(记者刘旸)2022斯诺克欧洲大师赛18日在德国菲尔特进行了32强对战,中国队选手颜丙涛吴宜泽分别横扫里奇沃顿和麦克劳德,赵心童45憾负米尔金斯。图为4月23微信8。0。27正式版上线增加3个新功能昨天,微信发布了安卓8。0。27正式版。经过亲测,本次微信安卓8。0。27正式版更新的内容,和此前推出的内测版本区别不大,主要都是一些小调整。1聊天新增全屏输入当聊天输入内容超过2太香!iPhone8升级iOS15。6。1正式版,丝滑如初的体验,值得升级最近2天大家都在讨论自己的iPhone建议升级iOS15。6。1吗?不少老机型例如iPhoneX,iPhone11升级后都带来了难以置信的优化,那么作为最后一代带有TouchID的6次助攻!36岁老将宝刀不老,昔日快马变喂饼大师,谢晖淘到宝了20战胜沧州雄狮,大连人凭借本场胜利反超沧州雄狮,升至积分榜第14位,保级形势大好。本场比赛,36岁的老将闫相闯为林良铭送出助攻,这是他本赛季的第6次助攻,仅次于榜首的斯坦丘,宝刀腾讯悄悄宣布,QQ空间一功能将停运,应用内数据将被删除或匿名化8月19日消息,腾讯QQ空间花藤团队宣布花藤将于10月18日停止运营。公告称,花藤由于业务方向调整,将于2022年10月18日14时59分59秒停止运营。届时将关闭服务器,用户无法事关交易!淘宝推出多地址下单功能,覆盖90以上商家天下网商杨洁编辑吴羚玮淘宝天猫再次对交易环节动刀。天下网商发现,最近,淘宝App版本更新,并且发布了一项新功能,下单可选多个地址凑单更自由,收货不用愁。过去,当消费者同时想买多件商折叠屏新宠发布,三星GalaxyZFlip4带动品质升级日前,三星第四代折叠屏手机三星GalaxyZFlip4正式发布,坚持以简约时尚以人为本的设计理念,并在设计功能性与实用性上都做出了更多升级,为其收获了不小的关注度。对于一直想入手一巡林小队,出发!原神新角色提纳里分享H5正式上线巡林小队,出发!原神新角色提纳里分享H5正式上线。扫描图中二维码立即参与。道成林里生物种类多样,环境复杂,有时可能还暗藏着危险。不过,巡林官提纳里是一个厉害的师父,见习巡林员柯莱跟隔夜水隔夜肉隔夜饭菜到底能不能吃呢一日三餐都离不开食物,很可能会出现食物剩下的现象,大部分人都会将食物放在冰箱里储存,我们所说的隔夜食物,就是只放置了一夜的食物吗?准确地来说,隔夜食物是放置时间超过58个小时的食物改口向中国供应78台光刻机?ASML公司变脸,2大原因不可忽略众所周知,自上世纪40年代以来,美国就凭借着超强的科技实力,成功问鼎全球超级大国的宝座。在互联网的时代下,科学技术的发展对于一个国家的综合实力起着至关重要的作用。发展至今,作为全球5个月卖出32套房,SOHO中国出租率跌至80,潘石屹笑不出来了对于刚刚过去不久的2022年上半年,SOHO中国不太平静。8月18日,SOHO中国公布2022年上半年业绩。财报显示,公司营业收入约8。96亿元,全部为租金收入,同比增长约11。上比亚迪是功臣!福布斯中国发布最佳CEO榜单王传福登顶榜首近日,福布斯中国发布了2022中国最佳CEO榜单,比亚迪创始人王传福登顶榜首。与去年相比,今年50位上榜者中,有44位新面孔,但平均年龄仍为54岁。(图片来自福布斯中国官方)具体来中国大订单空客7月交付46架飞机路透社看到未交付的空客A320neo系列飞机停在这家欧洲飞机制造商位于布拉尼亚克的工厂外空中客车公司周一证实,由于供应紧张导致工厂外的半成品飞机没有发动机,因此7月份的交付速度有所溢价5倍买壳,步长制药被疑利益输送,还能做中国的强生吗文财经天下周刊胡文柳编杨洁8月17日晚,步长制药发布公告称,已收到上交所监管工作函,内容直指公司日前进行高溢价收购的合理性。在一周前的8月10日晚,步长制药曾发布公告称,控股子公司国际空间站遇麻烦,航天服漏水漏电,俄宇航员希望参观中国空间站一段时间以来,退役在即的国际空间站问题不断,如今,宇航服又出现了问题因宇航服电气问题,舱外任务被叫停据环球网援引塔斯社报道,由于宇航服的电源出现故障,导致俄罗斯宇航员阿尔捷米耶夫提养好肝脏,脸色好,眼睛也明亮,给大家分享几个养肝茶千金方言肝主魂,为郎官,随神往来,谓之魂,魂者,肝之藏也。目者,肝之官,肝气通于目,目和则能辨五色矣。肝藏血,血舍魂,在气为语,在液为泪肝气虚则恐,实则怒。凡人卧,血归于肝,肝受血金爵体育报道NBA最新战况戴托昆波轮休希腊热身赛仍击退土今天进行的卫城锦标赛中,安戴托昆波虽然轮休未出赛,但他的弟弟K。安戴托昆波(KostasAntetokounmpo)拿下19分13篮板,加上效力独行侠的多西也进帐16分4助攻3篮板金爵体育资讯08年奥运会男篮纪录片将登场韦德詹皇协助制作Netflix官方宣布,将会和韦德(DwyaneWade)詹姆斯(LeBronJames)合作制作一部有关美国男篮在2008年北京奥运重夺金牌的纪录片,预计在10月7日播出。当年这神奇的安化云台山,带您走进美丽的云上茶园旅行,是一个可以让人放松,是在生活中迷失的人们,重新找回自我。踏上了旅行,就去享受此次的旅行。生活中,我们由于在城市每天为工作的奔波,其实,一处美丽的风景就能让我们感到分外愉快放松
中国斯诺克集体丑闻案件进展背后两大利益集团,丁俊晖接受调查前段时间,世界台联宣布对10名中国斯诺克运动员进行禁赛处罚,案件也在持续调查中。如今,中国斯诺克涉假案有了最新进展,两名年轻天才球员颜丙涛和赵心童一忧一喜,前者打假球的行为基本被坐人事普利司通中国任命新任总经理,目前在中国拥有约4200名员工文懂车帝原创常思玥懂车帝原创行业日前,普利司通(中国)投资有限公司(以下简称普利司通中国)发生人事变动,奥古斯丁佩德罗尼于2023年1月起就任普利司通中国总经理一职。普利司通(中国美国报废卫星今日或坠落朝鲜半岛据韩国中央日报报道,韩国科学技术信息通信部1月8日表示,美国航天局一颗报废卫星正在坠入地球大气层,残骸可能于今天(9日)坠落在朝鲜半岛。该部门已发出警戒警报,并提醒民众注意安全。这2022全国省市投资热度排行榜江苏一骑绝尘,锡苏双雄争霸从园区世界网获悉,最新的2022年全国省市投资热度排行榜出炉,该排行榜统计排名的考量维度主要是投资项目数量投资项目质量招商活动组织招商体系建设。在省市层面(不含直辖市和港澳台),江东莞这个镇有明清建筑群,规模大,环境美,房子雕刻讲究头条创作挑战赛原题红墙青瓦石板路,旧祠古榕翡翠湖访南社清明古村宋守娟崇山欲尽见古村,绿瓦青砖旧礼存。借问农家源何处,乌衣巷口谢族孙。在广东省东莞市茶山镇,聚集着珠三角最具代表性的明产业建圈强链案例丨金牛区引入航天长峰高端医疗装备智能制造项目每经编辑赵博渊2020年,航天二院成都分院落地金牛区,带动下属北京航天长峰股份有限公司(以下简称航天长峰)项目落地。航天长峰是以中国航天高端技术和应用成果为基础,航天军工企业为背景2022年公募基金成绩单出炉网红基金去年翻车多小体量黑马出圈图视觉中国羊城晚报全媒体记者丁玲随着2022年落下帷幕,公募基金全年成绩单也出炉。羊城晚报记者梳理发现,在此前两年由于市场整体环境较好而走红的一大批网红基金经理,2022年的收益情春节不打烊多家快递公司高薪留人1月6日,沈阳某菜鸟驿站快递件倍增,室外邮件堆积如山,市民排队取件供图视觉中国今年春节前又如往年一样,一份所谓快递停运时间表的清单在网上流传。这也让不少快递公司再次重申今年春节不打天文学家揭示了超大质量黑洞周围神秘的无线电泡的秘密美国国家科学基金会的绿岸望远镜(GBT)揭示了有关围绕一个超大质量黑洞的神秘无线电泡的新信息。在一篇研究星系团MS0735的新论文中,该出版物的主要作者JackOrlowskiSc当宇航员的代价是什么,这件事的痛苦,超乎你的意料1966年,我们第一次登上外层空间,目睹了我们生活的世界。在茫茫的宇宙中,我们的太空之梦,在我们这一代,已经成为了真实。但是,第一次进入宇宙,对于航天员来说,却是一件非常冒险的事情不可一世的宁泽涛,终究为自己的任性付出了代价文文亦范编辑小丁有人曾说人们往往把任性叫做自由,但是任性只是非理性的自由,人性的选择不是出于意志的理性,而是出于偶然的动机和对外在世界的依赖。对于我们而言,也想在生活中工作中有些任