#整理了一些博文作为高并发相关理论的学习笔记,同时加上了一些个人的理解,尊重原创者,文章属性就设为转载吧,参考博文的链接已附在最后。
高并发
并发,其实就是通过设计可以同时处理多个请求。
而高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求。
并发能力的衡量标准
一个系统的并发能力大概有这么几个参数来决定的。
(1)响应时间:系统对请求作出的响应时间(请求 客户端–>服务器–>客户端)
(2)吞吐量:单位时间内处理的请求数量
(3)QPS:每秒可以处理的请求数
(4)并发用户数:同时承载正常使用系统功能的用户数量
实现高并发的方法
大型网站,比如门户网站。在面对大量用户访问、高并发请求方面,基本的解决方案集中在这样几个环节:
- 使用高性能的服务器
- 高性能的数据库
- 高效率的编程语言
- 高性能的 Web 容器
以上的几个方面在一定程度上意味着更大的投入,会经常遇到瓶颈,没有很好的扩展性,所以还没法根本解决大型网站面临的高负载和高并发问题。
下面从较低成本、高性能和高扩张性的角度的一些经验:
- 分布式设计
- HTML 静态化
- 图片服务器分离
- 数据库集群和库表散列
- 缓存
- 镜像
- 负载均衡
- …
1. 改进程序,上个锁——synchronized
高并发量也就意味着多个线程同时在程序中运行,这样就会导致数据的不安全性,体现在两个方面,一是存在共享数据,另外一个就是共享数据可能被多个线程同时操作。而如果要保证多个线程同时访问一个资源的时候,那么就要给上限制,就是当一个线程访问完一个资源之后,其他的线程才能进来访问。这就需要一把锁–互斥锁!
2. 改进系统——分布式
根据互联网分布式架构设计,提高系统并发能力的方式,方法论上主要有两种:垂直扩展(Scale Up)与水平扩展(Scale Out)
2.1 垂直扩展——不断的提高单机处理能力
垂直扩展的方式又有两种:
- 增强单机硬件性能,例如:增加 CPU 核数如 32 核,升级更好的网卡如万兆,升级更好的硬盘如 SSD,扩充硬盘容量如 2T,扩充系统内存如 128G;
- 提升单机架构性能,例如:使用 Cache 来减少 IO 次数,使用异步来增加单服务吞吐量,使用无锁数据结构来减少响应时间。
在互联网业务发展非常迅猛的早期,如果预算不是问题,强烈建议使用“增强单机硬件性能”的方式提升系统并发能力,因为这个阶段,公司的战略往往是发展业务抢时间,而“增强单机硬件性能”往往是最快的方法。
不管是提升单机硬件性能,还是提升单机架构性能,都有一个致命的不足:单机性能总是有极限的。所以互联网分布式架构设计高并发终极解决方案还是水平扩展。
2.2 水平扩展——添加服务器(nginx反向代理)
添加了服务器的数量,也就所谓的服务器分布式集群。
在水平扩展模型中,是通过增加更多的系统成员(性能或速度还是原来的一样)来提高负载能力的。(如增加相同的服务器)
3. 数据库
数据库是大多数应用所面临的首个SPOF(single point of failure,单一故障点)。
常用的优化措施是 M-S(主-从)方式进行同步复制,将查询和操作和分别在不同的服务器上进行操作。
推荐的是 M-M-Slaves 方式,2个主 Mysql,多个 Slaves,需要注意的是,虽然有2个 Master,但是同时只有 1 个是 Active 的,我们可以在一定时候切换。之所以用 2 个 M,是保证 M 不会又成为系统的 SPOF。
Slaves 可以进一步负载均衡,可以结合 LVS,从而将 select 操作适当的平衡到不同的 slaves 上。
以上架构可以抗衡到一定量的负载,但是随着用户进一步增加,你的用户表数据超过 1 千万,这时那个 M变成了 SPOF。你不能任意扩充 Slaves,否则复制同步的开销将直线上升,怎么办?我的方法是表分区,从业务层面上进行分区。最简单的,以用户数据为例,根据一定的切分方式,比如 id,切分到不同的数据库集群去。
全局数据库用于 meta 数据的查询。缺点是每次查询,会增加一次,比如你要查一个用户 nightsailer,你首先要到全局数据库群找到 nightsailer 对应的 cluster id,然后再到指定的 cluster 找到 nightsailer 的实际数据。每个 cluster 可以用 M-M 方式,或者 M-M-Slaves方式。这是一个可以扩展的结构,随着负载的增加,你可以简单的增加新的 cluster 进去。
4. 数据库集群和库表散列
大型网站都有复杂的应用,这些应用必须使用数据库,那么在面对大量访问的时候,数据库的瓶颈很快就能显现出来,这时一台数据库将很快无法满足应用,于是我们需要使用数据库集群或者库表散列。
在数据库集群方面,很多数据库都有自己的解决方案,Oracle、Sybase、MySQL 等都有很好的方案,常用的 MySQL 提供的 Master/Slave 也是类似的方案,你使用了什么样的 DB,就参考相应的解决方案来实施即可。
上面提到的数据库集群由于在架构、成本、扩张性方面都会受到所采用 DB 类型的限制,于是我们需要从应用程序的角度来考虑改善系统架构,库表散列是常用并且最有效的解决方案。我们在应用程序中安装业务和应用或者功能模块将数据库进行分离,不同的模块对应不同的数据库或者表,再按照一定的策略对某个页面或者 功能进行更小的数据库散列,比如用户表,按照用户ID进行表散列,这样就能够低成本的提升系统的性能并且有很好的扩展性。
5. HTML 静态化
其实大家都知道,效率最高、消耗最小的就是纯静态页面,所以我们尽可能使我们的网站上的页面采用静态页面来实现,这个最简单的方法其实也是最有效的方法。但是对于大量内容并且频繁更新的网站,我们无法全部手动去挨个实现,于是出现了我们常见的信息发布系统 CMS,像我们常访问的各个门户站点的新闻频道,甚至他们的其他频道,都是通过信息发布系统来管理和实现的,信息发布系统可以实现最简单的信息录入自动生成静态页面,还能具备频道管理、权限管理、自动抓取等功能,对于一个大型网站来说,拥有一套高效、可管理的CMS 是必不可少的。
同时,html 静态化也是某些缓存策略使用的手段,对于系统中频繁使用数据库查询但是内容更新很小的应用,可以考虑使用 html 静态化来实现,比如论坛中论坛的公用设置信息,这些信息目前的主流论坛都可以进行后台管理并且存储再数据库中,这些信息其实大量被前台程序调用,但是更新频率很小,可以考虑将这部分内容进行后台更新的时候进行静态化,这样避免了大量的数据库访问请求高并发。
6. 静态资源服务器分离或者仅图片服务器分离
基本上大型网站都会采用的策略,因为对于Web 服务器来说,不管是 Apache、IIS 还是其他容器,图片是最消耗资源的,他们都有独立的图片服务器,甚至很多台图片服务器。这样的架构可以降低提供页面访问请求的服务器系统压力,并且可以保证系统不会因为图片问题而崩溃,在应用服务器和图片服务器上,可以进行不同的配置优化。
附相关概念的总结:
- 水平扩展:加人,垂直扩展:喝红牛。喝红牛的体现为工作模式的优化,就是处理能力的提升。
- 同步才有阻塞和非阻塞之分,因为他要等。阻塞就是傻等,等到完成为止。非阻塞就是看一下没有完成就干别的事情去了,然后过一些时间在回来看完成没有,一直到完成为止。这两者的区别在于等的方式不同!
- 异步没有阻塞非阻塞之分,都是非阻塞,因为他根本不需要等。异步都必定有回调接口(回调通知),任务完成后会接收到通知。
- 同步:主动等待,异步:被动接受通知。
- 同步 servlet 阻塞了 servlet 容器的线程导致任务排队/丢弃,限制了吞吐量。
- webflux 实现高吞吐量关键在于异步,不需要等待。
- webflux 的高吞吐量并不会让你的任务更加快,任务处理该多少时间还是多少时间。
————————————————
参考链接:
https://www.imooc.com/article/details/id/27729