版权声明:个人收集,转载注明,谢谢支持 https://blog.csdn.net/qq_42629110/article/details/84979482
高并发问题
从技术角度,秒杀,抢票对于web系统是一个巨大的考研,当web系统一秒内收到数以万计甚至更多请求时,系统的优化和稳定至关重要,目前并没有权威的技术和设计,只有长期的经验总结
高并发衡量指标
- 系统吞吐量
- 是指在给定的时间段内系统完成的请求的数量
- 即系统的吞吐量越大,说明系统在单位时间内完成的用户或系统请求越多,系统的资源充分利用
- QPS(Query Per Second)
- 每秒响应的请求数,也就是最大的吞吐量
- TPS(Transaction Per Second)
- 每秒处理完事务的次数,是相对于整个系统的
- 并发量
- 系统能同时处理的请求数
- 一般系统,并发量大概是在线人数十分之一
- RT
- 平均响应时间
- 计算公式
- QPS=并发量/RT
处理高并发
前端到存储层,请求量要越来越少
- 前端
- 提供严格的数据校验,防止垃圾请求提交
- 用JS就把请求给拦下来了
- 提供良好的提示/反馈机制,防止用户反馈感太差而多次提交请求
- 比如进度条,服务器正在处理的反馈…
- 可以通过js初步控制用户连续点击提交
- 比如禁止重复点击,按钮不可以用
不过前端并不是能够核心的处理高并发,只是尽量的使得后台不会收到过多的垃圾请求
- 比如禁止重复点击,按钮不可以用
- 提供严格的数据校验,防止垃圾请求提交
总结前端:
严格数据校验,用户友好提示与反馈,防止重复点击
减少垃圾请求
- 负载均衡服务器
- 负载均衡服务器通常是互联网请求的第一个入口,是处理高并发的关注核心
- 过滤无效请求,竟可能的使得无效请求在这一层被拦截掉,而不会到达web服务器,从而造成web服务器的额外压力
- 针对一个账号连续发送请求的情况,可以加入验证码,第一次提交无需验证码,第二次请求或者第三次提交则需要提供验证码,负载均衡根据验证码的内容过滤掉脚本或者插件重复提交的无效请求
- 注意:验证码的校验功能应该在负载均衡服务器就处理好,而不是交到web服务器去判断,web服务器在接受到某个账号的多个请求的时候,可以将验证码写入到redis缓存服务器中,nginx通过lua操作redis进行验证码的校验
- 提供负载均衡算法,将不同的请求合理的分发的不同的服务器上.分散高并发的压力
- 轮询
- 权重
- iphash
- 限流,对于请求过多的时候,设置限制通过的请求数量,部分告知系统繁忙,稍后再试,从而保证系统的持续可用
- 常见的限流算法
- 令牌桶算法
- 添加令牌,如果满了则令牌丢弃
- 漏桶算法
- 获取令牌,如果没有了返回系统繁忙
- 令牌桶算法
- 常见的限流算法
总结负载均衡
过滤无效请求,请求分流,请求限流
使用redis+lua实现验证码过滤无效请求,合适的负载均衡算法进行请求分发,限流算法,令牌桶,漏桶算法
redis服务器
- redis服务器是应对高并发的有效手段,大量请求被拦截在redis服务层,从而保证数据库的可靠性以及高效性
- 作用
- 换成频繁访问数据(热数据),提供高效的数据读取方案,环节数据库层面的访问压力
- 解决高速读写场景下数据一致性和高性能问题
- 数据共享功能,session数据,验证码等数据可以放在缓存服务器中方便分布式服务器进行操作
- 问题:
- 缓存失效
- 换成通常会设置超时时间避免读取到国企数据的问题,换成一旦超时请求就回去数据库查找数据,进行缓存重建,但是如果是高并发的场景下,可能会造成大量请求因为缓存失效的原因到达存储层,从而造成缓存层压力
- 解决方案
- 过期时间散列
- (常用)分布式互斥锁,只允许一个线程执行重建换成
- 永不失效
- 从redis上来看,确实没有过期时间
- 把过期时间存在key对应的value中,如果发现要过期了,通过一个后台的异步现场进行缓存的重建
- 缓存击穿
- 对于一个请求如果在redis中没有找到,则会发送到数据库中进行查找,并且返回数据缓存到redis中,但是如果数据库中也没有找到这个数据,则直接返回空,但是如果有人利用这个漏洞,频繁范文一个不存在的数据,则会大量请求达到数据层,这种现象称为缓存击穿
- 解决方案
- 换成null值并设置一个短的过期时间
- 布隆过滤器拦截,利用redis的bitmaps喜欢i先Bitmaps查看是否存在,再决定是否去查询数据 - 缓存雪崩
- 当缓存服务器因为本身原因,宕机,缓存失效,缓存击穿等,导致大量的请求达到数据库服务器,导致数据库宕机,最后连锁反应导致数据库集群连续崩溃,发生雪崩
- 解决方案
- 保证缓存层的服务高可用性,通过哨兵模式,分片模式构建高可用的redis集群
- 依赖隔离组件未后端限流并降级Hystrix,在实际项目中,需要对重要的资源,例如redis,mysql,外部接口都进行隔离,让每种资源都单独运行在自己的线程池中,即便个别资源出现了问题也对其他资源不产生影响
- 缓存失效
redis总结
拦截请求,提供高效数据读写,同时提高自身的高可用
缓存失效,缓存击穿,缓存雪崩等问题逐个解决
换成失效,散列,分布式锁,永不过期但设置value为过期时间异步清除
缓存击穿,缓存null值,布隆过滤器,将所有数据进行集合对比,没有在继续向下访问
缓存雪崩,实现redis的高可用,哨兵模式,分片模式等,同时使用服务隔离组件,隔离各个资源避免雪崩
- 后台服务器
- 单台服务器往往不足以支撑高并发的请求,因此通常需要分布式的方式分摊请求的压力使得单台服务器的压力不至于过大
- 分布式,按照业务拆分,他们之间相互隔离,降低数据的复杂性,模块之间可以通过一些方式进行通讯(HttpClient,webservice,MQ,RPC等)
- 集群,将系统拷贝成多个互不相干的同样的系统,分别部署,起到分流处理的作用,横向扩展
- 结合分布式和集群,按照业务分为多个子系统然后复制多个子系统共同对外提供服务,通过负载均衡分流
- 问题
- 数据共享的问题,通过redis解决
- MQ消息中间件
- MQ消息中间件通常作为分布式服务之间的消息通讯机制,可以起到异步请求,流量削峰的作用
- Mysql数据库
- 主从复制,读写分离,支持多Master
- 问题
- 如何实现读写分离
- 引入mycat数据库中间件,会虚拟出来一张表,拦截sql通过该表分发到数据库集群中
- 如果数据的选择性不高并且数据量很大(千万级别)需要考虑到分库分表
- 分表,把一张表按照一定的规律进行拆分,查询时就带范围条件进行查询
- 分库,数据库和数据库之间并没有关系,减少数据库的压力
- 如何实现读写分离
- 分布式事务
- 对于分布式系统而言,一个具体的业务需要同时调用两个或多个服务,每个服务又可能操作不同的数据库,所以不能用本地的数据库事务进行事务管理,所以此时不能用本地的数据库事务进行事务管理此时就需要分布式事务
- 解决方案
- 两段提交协议(2PC)
- 服务共同约定好在一个事务协调器,必须两个服务确认提交后事务才能提交
- 第一阶段是表决阶段,所有的参与者都将自身事务是否能够成功的信息反馈给协调者,第二阶段是执行阶段,协调者根据所有参与者的反馈通知所有参与者,步调一致地在所有分支上提交或者回滚
- 缺点
- 两段提交方案锁定资源时间太长,对性能的影响很大,不适合解决对性能要求很高的互联网项目
- 补偿型事务(TCC)
- TCC在电商,金融领域落地比较多,TCC方案其实是两段提交的一种改进,其将整个业务逻辑的每个分支显式的分成Try,Confirm,Cancel三个操作,Try部分完成业务的准备工作,confirm部分完成业务的提交,cancel部分王城事务的回滚
- 缺点
- 对应用的侵入性很强,每个业务逻辑都得编写饭业务逻辑,改造成本很高
- 基于MQ的最终事务一致性,代码改造性很低
- 两段提交协议(2PC)
- 其他
- 文件管理系统
- 动静态分离
- 卖票,预定
Mysql总结:
sql优化,读写分离,分库分表,分布式事务的解决
sql执行速度越快是的数据库的吞吐量越高,读写分离通过mycat数据库中间件,拦截sql进行sql执行的分发,分库分表,分布式事务的解决从2PC到TCC补偿型事务,主流的MQ消息中间件的最终一致性实现分布式事务最为简单常用
其他的技术
FastDFS对分布式系统的文件的集中管理
Freemarker静态页面生成技术以及Nginx提供Http服务器功能
卖票后通过对预定的判断解决抢购抢票等高并发高速读写情形下的请求拦截