高并发

总结:想要高并发,首先要高性能,性能工程对于性能优化是有一些原则方法论的

单个数据库每秒两三千并发就基本扛不住了

高性能三板斧:扩容、异步、缓存

系统拆分

将单体系统拆分成多个系统或者多个服务,每个子系统使用自己的数据库,提高并发度

大部分的系统都是需要经过多轮拆分的,第一轮拆分将系统粒度划的小一点,可能随着业务的发展,单个系统会变得更复杂,所以需要进一步的拆分

拆分的维度:

局部并发原则

将同步调用的外部服务拆分为多个无关异步调用,来提升性能

高性能流程

容量规划

使用压测监控预测等确定要支撑多少性能指标 确定哪些性能指标的基准水位线

负载测试

测试系统在正常运行压力下的各项指标,这个流程是一个长期的流程以保证系统性能可预测,出现问题也能发现问题在哪

压力测试

要压到发现系统失效点,远高于正常的负载 只对关键、瓶颈业务进行测试 好钢用在刀刃上

失效点关注于响应时间、内存、失败率等异常指标

APM监控

弹性扩缩容

根据监控,使用策略,管理资源

高并发读

策略:加缓存

大部分高并发的场景,都是写多读少,使用缓存,可以有效抗住高并发

对于缓存需要考虑 雪崩 击穿 穿透 等缓存问题

策略:并发读

策略:重写轻读

某些事件产生的数据提前聚合好 等需要的时候直接读取即可 而非在需要的时候实时计算

读写分离

大部分对数据库的请求都是读多写少,所以读写分离,分配多一些机器给读请求,能有效提高性能

读写分离带来的问题及解决方案:

  1. 复制延迟
    • 针对特定业务 读写都在主机上 非核心业务使用从机
    • 读从机,发现从机上的数据是旧的 则二次读取主机
  2. 分配机制 如何让客户端将读写操作区分开来,然后访问不同的数据库服务器
    • 客户端分离 TDDL shardingSphere 动态数据源也可以实现
    • 数据库中间件 [MyCat](/中间件/数据库/MyCat.html), MySQL Router,

高并发写

数据分片

任务分片

异步化

减少等待、Y轴扩展、削峰填谷

批量

妥协

资源是有限的 并发无上限

负载均衡

调度后方的多台机器,以统一的接口对外提供服务,承担此职责的技术组件被称为“负载均衡”。

“四层”的意思是说这些工作模式的共同特点是都维持着同一个TCP连接,而不是说它就只工作在第四层

典型的负载均衡架构

链路负载均衡

通过DNS解析来完成,每次 DNS 解析的结果都会在几个 IP 地址之间进行轮询,从而实现负载均衡。优点是可以返回离用户地理位置更近的服务器,缺点是DNS具有多级结构,DNS解析结果可能被各级缓存,修改DNS记录后,需要比较长的时间才能生效。大型网站基本使用了 DNS 做为第一级负载均衡手段,然后在内部使用其它方式做第二级负载均衡

硬件负载均衡

操作系统负载均衡

利用系统级别的中断以及多队列网卡等来充分利用资源 达到负载均衡的功能

客户端负载均衡

传统客户端微服务

服务网格的客户端代理负载均衡

HTTP负载均衡

负载均衡服务器使用某种负载均衡算法计算得到服务器的 IP 地址之后,将该地址写入 HTTP 重定向报文中,状态码为 302。客户端收到重定向报文之后,需要重新向服务器发起请求

这样客户端需要两次请求,性能会受到一定影响

2020317145131

集群负载均衡

网络级别的负载均衡

数据链路层负载均衡

直接修改请求的数据帧中的MAC目标地址,让用户原本是发送给负载均衡器的请求的数据帧,被二层交换机根据新的MAC目标地址转发到服务器集群中对应的服务器,二层负载均衡器直接改写目标MAC地址的工作原理决定了它与真实的服务器的通讯必须是二层可达的。效率很高 网络层负载均衡:

IP隧道模式

对IP包进行封装,封装成一个新包发送到后端服务器,这种方式需要后端服务器持有一个VIP 这样才能直接响应请求,不够透明

NAT模式

直接由均衡器对IP头进行修改 所有数据报都要经过均衡器,这个均衡器很容易称为瓶颈 更彻底的NAT模式:均衡器在转发时,不仅修改目标IP地址,连源IP地址也一起改了,源地址就改成均衡器自己的IP,称作Source NAT(SNAT),在后端服务器的视角看来,所有的流量都来自于负载均衡器

应用层负载均衡:

该层的优势就在于比链路层 网络层可以得到更多的信息 从而做出更加智能的决策

负载均衡算法

任务平分类
压力均衡类
hash类

均衡器实现

LVS

D-NAT模式

DR模式

将RS的VIP配置在内核中

TUN模式

流程

node01:	ifconfig  eth0:8 192.168.150.100/24node02~node03:	1)修改内核:		echo 1  >  /proc/sys/net/ipv4/conf/eth0/arp_ignore 		echo 1  >  /proc/sys/net/ipv4/conf/all/arp_ignore 		echo 2 > /proc/sys/net/ipv4/conf/eth0/arp_announce 		echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce 	2)设置隐藏的vip:		ifconfig  lo:3  192.168.150.100  netmask 255.255.255.255		RS中的服务:node02~node03:	yum install httpd -y	service httpd start	vi   /var/www/html/index.html		from 192.168.150.1xLVS服务配置node01:		yum install ipvsadm 	ipvsadm -A  -t  192.168.150.100:80  -s rr	ipvsadm -a  -t 192.168.150.100:80  -r  192.168.150.12 -g -w 1	ipvsadm -a  -t 192.168.150.100:80  -r  192.168.150.13 -g -w 1	ipvsadm -ln验证:	浏览器访问  192.168.150.100   看到负载  疯狂F5	node01:		netstat -natp   结论看不到socket连接	node02~node03:		netstat -natp   结论看到很多的socket连接	node01:		ipvsadm -lnc    查看偷窥记录本		TCP 00:57  FIN_WAIT    192.168.150.1:51587 192.168.150.100:80 192.168.150.12:80		FIN_WAIT: 连接过,偷窥了所有的包		SYN_RECV: 基本上lvs都记录了,证明lvs没事,一定是后边网络层出问题

问题:

keepalived

作为一个通用工具,解决高可用问题

配置

vrrp_instance VI_1 {        state MASTER // 备服务器BACKUP        interface eth0        virtual_router_id 51        priority 100        advert_int 1        authentication {                auth_type PASS                auth_pass 1111        }        virtual_ipaddress {                172.17.0.100/16 dev eth0 label  eth0:3        }}virtual_server 172.17.0.100 80 {        delay_loop 6        lb_algo rr        lb_kind DR        nat_mask 255.255.255.0        persistence_timeout 0        protocol TCP        real_server 172.17.0.4 80 {                weight 1                HTTP_GET {                        url {                                path /                                status_code 200                        }                        connect_timeout 3                        nb_get_retry 3												delay_before_retry 3                }        }        real_server 172.17.0.6 80 {                weight 1                HTTP_GET {                        url {                                path /                                status_code 200                        }                        connect_timeout 3                        nb_get_retry 3                        delay_before_retry 3                }        }}