高并发类题目的解题思路

最近也看了一些相关的题目,大概说一下这种题目的解决思路,仅作为参考

高并发问题的本质就是:资源的有限性

流量大的网站 如何处理高并发流量问题?
首先从开发者角度看:(一、架构层面;二、网站本地项目层面)

一、架构层面

1、硬件升级
2、负载均衡
3、服务器集群
4、分布式结构

提示一下:
负载均衡:
是一种优化手段,目的是为了让集群中的每台机器的负载保持均衡,这样就不会出现集群中某台机器挂了的情况;

集群:
多台机器做相同的业务,对外如一台机器在做事情一样,集群中任意一台机器挂了没有影响,因为其他机器还在工作;

分布式:
一个业务在不同的物理点上做,比如web服务器、应用服务器、数据库服务器,这三个节点分开部署在不同的机器上,共同完成一个业务;分布式的特点是,每个节点都不能挂,否则这个业务就不能完成了;当然,我们可以给分布式中的每个节点都做集群处理,这样可以降低分布式系统的单节点故障;

所以,针对自己业务量大小,对上述的负载均衡、服务器集群、分布式结构,任意选用方案。

二、网站本地项目层面
1、页面静态化
2、缓存技术(Memcache、Redis等)
3、数据库优化
4、CDN
5、禁止盗链
6、控制大文件的上传下载

以上参考:https://blog.gaomeluo.com/archives/chulibingfa/

另外,从用户视角来看(客户端和服务端)

高并发带来的问题
服务端的处理和响应会越来越慢,甚至会丢弃部分请求不予处理,更严重的会导致服务端崩溃。

高并发处理的基本思路
1)从客户端看
尽量减少请求数量,比如:依靠客户端自身的缓存或处理能力

尽量减少对服务端资源的不必要耗费,比如:重复使用某些资源,如连接池客户端处理的基本原则就是:能不访问服务端就不要访问

2)从服务端看
增加资源供给,比如:更大的网络带宽,使用更高配置的服务器,使用高性能的Web服务器,使用高性能的数据库

请求分流,比如:使用集群,分布式的系统架构

应用优化,比如:使用更高效的编程语言,优化处理业务逻辑的算法,优化访问数据库的SQL

基本原则:分而治之,并提高单个请求的处理速度

高并发处理的基本手段

1)客户端发出请求层面,常见的手段有:
尽量利用浏览器的缓存功能,减少访问服务端,比如:js、css、图片等
可以考虑使用压缩传输的功能,减少网络流量,也会提高传输速度
考虑使用异步请求,分批获取数据

2)前端接收客户端请求层面,常见的手段有:
动静分离,部分静态资源可以直接从Nginx返回
按请求的不同,分发到不同的后端进行处理,比如:负载均衡、业务拆分访问等
前面再加上一层来做多个Nginx的负载均衡,比如:LVS、F5等
还可以在更前面使用CDN服务
还可以对动态内容进行缓存,尽量减少访问后端服务

3)Web服务器层面,常见的手段有:
使用最新的JVM,并进行配置优化
对Web服务器进行配置优化,比如:调整内存数量、线程数量等
提供多个能提供相同服务的Web服务器,以实现负载均衡
仔细规划Web服务器上部署的应用规模
对Web服务器进行集群

4)Web应用层面,常见的手段有:
动态内容静态化
Java开发优化
优化处理业务逻辑的算法
合理高效的利用缓存
优化访问数据库的Sql,可以考虑利用存储过程等数据库的能力
合理使用多线程,加快业务处理
部分业务可以考虑内存数据库,或者是进行纯内存处理
尽量避免远程调用、大量I/O等耗时的操作
合理规划事务等较为耗资源的操作
合理使用异步处理
对部分业务考虑采用预处理或者预计算的方式,减少实时计算量
内部系统间的业务尽量直接调用、直接处理,减少WebService、工作流等

5)数据库层面,常见的手段有:
合理选择数据库的引擎,比如Mysql的InnoDB与MyISAM引擎
进行配置优化
可以考虑使用存储过程来处理复杂的数据逻辑
数据库集群,进行读写分离
合理设计数据库的表结构、索引等
分库、分表,降低单库、单表的数据量

 

以上参考:https://juejin.im/entry/5b58284ce51d451949093d09

 

另外,还有一些大流量和高并发的常规应对手段
扩容、动静分离、缓存、服务降级和限流。

(以下整体会有点乱,可以大概熟悉一下)

限流的常用算法和实践思路
目前主流的算法主要有三种:令牌桶算法、漏桶算法和计数器算法。

令牌桶算法:主要限制流量的流入速率,允许出现一定程度的突发流量。Nginx的限流模块就是使用的这种算法实现的。

每秒会有r个令牌按照固定速率放入桶中。
桶的容量是固定不变的,如果桶满了再放入令牌,则溢出。
若桶中的可用令牌不足,则改请求会被进行限流处理(被抛弃或缓存)。

漏桶算法:主要限制流量的流出速率,并且流出速率是固定不变的
可以以任意速率向桶中流入水滴。
桶的容量是固定不变的,如果桶满了则溢出。
按照固定的速率从桶中流出水滴。
Google的Guava也实现了基于令牌桶算法那样的平均速率限流,RateLimiter抽象类。

Nginx可以使用限流模块在接入层实现令桶牌算法限流,
limit_zone 定义每个IP的session空间大小。
limit_zeq_zone定义每个IP每秒允许发起的请求数。
limit_conn 定义每个IP能够发起的并发连接数。
limit_req 等待处理的请求队列数量。
生产环境中的商品抢购可以使用计数器算法,具体不同的sku限流规则配置在配置中心内,支持动态更改。可抢购次数的扣减操作,既可以用redis,也可以用JVM。如果是集群并且选择用JVM,则要根据总并发数量除以集群数量,得出单台机器的并发数。(比如总并发数5000,集群机器10台,则每台机器的并发为5000/10=500)。

抢购商品高并发读需求
对于一件抢购商品的流量来说,因为key是同一个,所以流量必然会都引入到同一个redis缓存节点中,这时就容易出现单点故障。因此有下面两种解决方式:
1. 在每个master节点都挂slave从节点,当主节点挂了可以自动顶上。
2. 多级Cache方案,多用LocalCache来过滤掉一部分流量。
- 本地缓存一般只缓存一些热点商品数据,缓存内容一般是商品详情和商品库存。
- 本地缓存跟分布式缓存的同步一般有两种方式:一种是定时主动拉取更新策略。这种会存在一定时间的不一致,要视业务情况而定,例如库存,暂时的不一致导致超卖,单到真正下单的时候还会再进行库存的判断,所以影响较小,可以接受。这种方式要注意关掉缓存的定时失效,防止当用户流量突然过大,都到分布式缓存中拉取数据;第二种方式是每次商品更新,都发布一个消息,订阅此消息的节点监听到后再更新本地缓存的内容。

实时热点自动发现方案
可以将交易系统产生的相关数据,以及在上游系统中埋点上报的相关数据异步写入日志系统中,然后通过实时热点自动发现平台对收集到的日志数据做调用次数统计和热点分析。数据符合热点条件后,就立即通知交易系统做好热点保护。

redis使用watch命令实现高并发抢购需求
一般高并发这里,不用悲观锁,会迅速增加系统资源;而使用队列,容易造成请求堆积,内存效果过快。所以一般使用乐观锁,可以用redis的watch命令实现。
watch命令会监视给定的key,当exec时,如果监视的key从调用watch后发生过变化,则事务会失败。注意watch的可以是对整个连接有效的,事务也一样。如果连接断开,监视和事务都会被自动清除。当然exec,discard,unwatch命令都会清除连接中的所有监视。


缓存雪崩,缓存穿透,缓存并发,缓存预热,缓存算法
缓存雪崩:可能是因为数据未加载到缓存中,或者缓存同一时间大面积的失效,从而导致所有请求都去查数据库,导致数据库CPU和内存负载过高,甚至宕机。解决思路:
加锁计数(即限制并发的数量,可以用semphore)或者起一定数量的队列来避免缓存失效时大量请求并发到数据库。但这种方式会降低吞吐量。
分析用户行为,然后失效时间均匀分布。或者在失效时间的基础上再加1~5分钟的随机数。
如果是某台缓存服务器宕机,则考虑做主备。
缓存穿透:指用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候,在缓存中找不到,每次都要去数据库中查询。解决思路:
如果查询数据库也为空,直接设置一个默认值存放到缓存,这样第二次到缓冲中获取就有值了,而不会继续访问数据库。设置一个过期时间或者当有值的时候将缓存中的值替换掉即可。
可以给key设置一些格式规则,然后查询之前先过滤掉不符合规则的Key。
缓存并发:如果网站并发访问高,一个缓存如果失效,可能出现多个进程同时查询DB,同时设置缓存的情况,如果并发确实很大,这也可能造成DB压力过大,还有缓存频繁更新的问题。解决思路:
对缓存查询加锁,如果KEY不存在,就加锁,然后查DB入缓存,然后解锁;其他进程如果发现有锁就等待,然后等解锁后返回数据或者进入DB查询。
缓存预热:目的就是在系统上线前,将数据加载到缓存中。解决思路:
数据量不大的话,在系统启动的时候直接加载。
自己写个简单的缓存预热程序。

缓存算法:
FIFO算法:First in First out,先进先出。原则:一个数据最先进入缓存中,则应该最早淘汰掉。也就是说,当缓存满的时候,应当把最先进入缓存的数据给淘汰掉。
LFU算法:Least Frequently Used,最不经常使用算法。
LRU算法:Least Recently Used,近期最少使用算法。
LRU和LFU的区别。LFU算法是根据在一段时间里数据项被使用的次数选择出最少使用的数据项,即根据使用次数的差异来决定。而LRU是根据使用时间的差异来决定的。
————————————————
版权声明:本文为CSDN博主「后海hh」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u010942020/article/details/79315067

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章