以前的两篇系统架构的博客中都提到了高并发、高可用技术,可是却都没有详细聊过,今天就好好聊一下常见的高并发技术。java
高并发技术的核心是分流;分别针对请求的各个环节,根据具体场景和业务特色采用不一样的分流方案,逐层逐级的分担系统压力,从而达到高并发能力。ajax
常见的高并发技术有:动静分离、缓存、异步并发、水平扩展等。分流简单来讲就是:一台服务器承担不了的流量,就让多台服务器共同分担;DB承担不了流量就让缓存来帮忙分担;等等。接下来讨论的全部内容都是围绕着分流来实现的。redis
现实中没有一招鲜吃遍天的美事儿,每个公司、每一种业务、每个场景、每个功能都有其不同凡响的特色,现实中通常都会根据业务特征、根据请求的各个环节特色,作针对性优化。数据库
一次请求主要分为四个阶段:客户端发起请求;经过网络将请求信息发送到服务端;服务端处理请求;服务端将结果返回给客户端。为了追求并发的极致,咱们能够针对每个阶段分别使用不一样的策略,来提高系统的并发性能。模型以下:缓存
这是一个漏斗型的模型,经过逐层过滤,将流量分散,让尽量少的请求到达底层。服务器
此模型的核心就是,根据各环节的特色,选择相应的优化策略,从而实现高并发的目的。微信
客户端优化技术主要指的是客户端经过缓存数据,减小访问服务端的次数,以实现下降服务端压力,达到支持更多并发量的需求。网络
常见的处理方式是:缓存不常常变更的内容,每隔必定时间更新一次,或者除非修改了不然较长时间不更新;如:更新微信公众帐号的头像时,手机端不会当即看到这个更新。另外,根据业务场景能够限制没必要要的请求;如:点击一个按钮,发送一次请求到服务端时,禁用按钮,避免因用户屡次点击,而发送没必要要的请求。数据结构
网络优化的核心目标是:将资源缓存到距离用户最近的网络节点上,这样除了能够省下大量网络带宽外,还能够达到最快的请求速度;通常针对静态资源。架构
经过静态化技术(将不常常变更的内容生成静态文件)或动静分离技术(例如H5+ajax),将静态的内容存储在CDN上,当用户查看一个页面时,只让少数的动态请求落到服务器端,其余内容从CDN上直接获取,这样就能够极大的减小服务器端的流量。
负载均衡的核心是让每台服务器以一个合适的负载来分担全部的请求。
常见的负载均衡方案有:随机、轮询、hash、一致性hash。固然在这些基础上有不少扩展,例如在负载均衡的机器中设置不一样的权重;根据key的范围不一样调用不一样的服务器等等。
a) 为何高效
缓存的结构通常都是key-value结构,经过key直接寻址,时间复杂度为O(1),这比DB的遍历比较来快了很是多;另外,很多的缓存中间件经过在内存中存储数据,不用从磁盘中获取数据,性能也就会很是高。
说明一下:大部分缓存中间件都会对value作一些扩充,让value也成为一个复杂的数据结构,例如Redis的Set、SortSet,若是须要在value中寻找某一个值,时间复杂度会退化成为O(N);这些数据结构提供了强大的功能,使用的时候注意合理使用,以免由于缓存乱用致使性能下降的问题。
b) 分布式缓存
如redis、tair、memcached等。
优势是:集群部署,不用考虑容量问题,数据支持持久化,支持高可用。
缺点是:由于服务器和缓存数据交换时存在一次网络交互,若是数据结构选择不合理或者并发量很是大或者每次交互的数据量较大时,可能会引发io阻塞等问题,需谨慎。
c) 堆缓存
经过java的堆来缓存数据。
优势是:速度很是快。
缺点是:存储数据量受限,断点数据丢失,分布式场景中若是出现不一致时,处理麻烦。
d) 磁盘文件缓存
将数据存储到服务器所在的磁盘上。
优势是:存储内容较堆内存多(少于分布式缓存),是持久化的。
缺点是:服务器迁移时也要迁移磁盘中的文件,分布式场景中若是出现不一致时,处理麻烦。
e) 注意事项
缓存数据和数据库数据不一致的问题。
缓存击穿问题。
缓存数据丢失问题(缓存通常都须要持久化的,为了保证性能缓存通常都不是同步持久化,因此是可能存在数据丢失问题的)。
高性能的IO通讯模型能够给系统带来巨大的性能提高。目前就较为成熟、高效的IO通行模型是NIO(也叫IO多路复用、异步阻塞IO)。
在java服务器前加一层Nginx服务器,它既能够提供良好的负载均衡能力,也可以支持很是高的并发。固然Nginx的高性能还与他的master-worker设计有关,几乎作到了无线程切换。
使用Dubbo进行RPC调用时,默认使用的Netty也是基于NIO的。