实战java高并发程序设计-java并发编程实战手册
来源:my.oschina.net/u/3772106/blog/1793561
高并发往往发生在活跃用户数量多、用户集中度高的业务场景,比如:秒杀活动、定时领红包等。
为了让业务顺利运行,为用户提供良好的交互体验,我们需要根据业务场景实现的预估并发数等因素,设计适合自己业务场景的高并发处理方案。
在这几年电子商务相关产品的开发中,有幸遇到过并发带来的各种坑。 一路上有很多血和泪。 这里总结作为自己的存档记录,分享给大家。 每个人。
01 服务器架构
从业务发展初期到逐渐成熟,服务器架构也从相对单一到集群再到分布式服务。
一个能够支持高并发的服务,需要一个好的服务器架构,需要负载均衡,数据库主从集群,nosql缓存主从集群,静态文件上传CDN。
大部分服务器需要运维人员配合搭建。
大致需要的服务器架构如下:
02 并发测试
高并发相关的业务需要进行并发测试,通过大量的数据分析评估整个架构所能支持的并发量。
测试高并发,可以使用第三方服务器或者自己的测试服务器,使用测试工具测试并发请求,分析测试数据,得到可以支持的并发请求数的评估。 这可以作为预警参考。
第三方服务:
并发测试工具:
03 实用方案
总体规划
每天的用户流量大,但比较分散实战java高并发程序设计,偶尔会出现用户高度集中的情况;
场景:用户登录、用户中心、用户下单等。
服务器架构图:
阐明:
场景中的这些业务,基本都是用户进入APP后操作的。 除了活动日(618、双11等),这些业务的用户量不会很高,而且这些业务相关的表都是大数据表,大部分业务都是查询操作,所以我们需要减少用户直接访问数据库的查询次数; 先查询缓存,如果缓存不存在,再进行DB查询,并缓存查询结果。
更新用户相关的缓存需要分布式存储,比如使用用户ID进行hash分组,将用户分布到不同的缓存中。 这样的缓存集总量不会很大,不会影响查询效率。
程序如:
上面的例子是一个比较简单的高并发架构,在并发量不是很高的时候可以很好的支持。 但是随着业务的增长,并发用户数的增加,我们的架构也会不断的优化演进。 比如业务是服务化的,每个服务都有自己的并发架构,自己的平衡服务器,分布式数据库,nosql主从集群,比如:用户服务,订单服务;
消息队列
秒杀、secgrab等主动服务,用户瞬间涌入,产生高并发请求
场景:定时收红包等
服务器架构图:
阐明:
场景中的定时收货是一个高并发的业务。 比如秒杀活动的用户适时涌入,DB瞬间受到暴击。 如果不能举行,将关闭并影响整个业务;
对于这种既有查询操作又有高并发insert或update数据的业务,上面提到的通用方案无法支持,并发时直接打到DB;
在设计这个业务的时候,会用到消息队列。 可以将参与用户的信息添加到消息队列中,然后写一个多线程程序消费队列,给队列中的用户分发红包;
程序如:
额外的:
许多服务可以通过消息队列来完成。
如:定时短信发送服务,使用sset(sorted set),发送时间戳作为排序依据,短信数据队列按照时间排序,然后写一个程序定时循环读取sset队列中的第一项,当前是否time exceeds the sending time 时间,如果超过,发送短信。
一级缓存
高并发请求连接缓存服务器超过服务器可接收的请求连接量,部分用户出现连接建立超时无法读取的问题;
因此,需要一种解决方案,在高并发的情况下,减少对缓存服务器的命中;
这时候就出现了一级缓存方案。 一级缓存使用站点服务器缓存来存储数据。 注意只存储部分请求量大的数据,要控制缓存的数据量。 不能过度使用站点服务器的内存。 影响站点应用的正常运行。 一级缓存需要以秒为单位设置过期时间。 具体时间根据业务场景设置。 目的是让数据获取在高并发请求时命中一级缓存,而不是连接缓存nosql数据服务器,减轻nosql数据服务器的压力
比如APP首屏的商品数据界面。 这些数据是公开的,不会为用户定制,也不会经常更新这些数据。 如果该接口的请求量比较大,可以加入一级缓存;
服务器架构图:
合理规范使用nosql缓存数据库,根据业务拆分缓存数据库集群,基本可以很好的支撑业务。 毕竟一级缓存使用的是站点服务器缓存,所以要好好利用。
静态数据
如果高并发请求数据没有变化,如果不能请求自己的服务器获取数据,可以减少服务器的资源压力。
如果更新频率不高,数据可以在短时间内延迟,可以将数据静态转换成JSON、XML、HTML等数据文件上传到CDN。 从缓存和数据库中获取。 当管理员操作后台编辑数据然后重新生成静态文件上传到CDN,这样在高并发的时候数据获取可以命中到CDN服务器上。
CDN节点的同步有一定的延迟,所以找靠谱的CDN服务器商也很重要
其他节目
关于上面的技术,不是三言两语就能解释清楚的。 其实内容很多,很多问题的答案其实很简单,但是背后的思路和逻辑并不简单。 如果你想学Java工程,高性能和分布式,简单易懂。 微服务、Spring、MyBatis、Netty源码分析等的朋友要坚持做...
04 层级、细分、分布
大型网站需要很好地支持高并发,这需要长期的规划设计
前期系统需要分层。 在开发过程中,将核心业务划分为模块化单元,根据需要进行分布式部署,可由独立团队进行维护和开发。
网站分层——图1 来自网络
05集群
独立部署服务器、应用服务器、数据库、nosql数据库,供用户集中业务访问。核心业务基本需要搭建集群,即多台服务器部署同一个应用,形成集群,通过负载均衡对外提供服务设备。 服务器集群可以为同一个服务提供更多的并发支持,所以当有更多的用户访问时,只需要在集群中添加一台新的机器即可。 此外,当其中一台服务器发生故障时,可以通过负载均衡故障转移机制将请求转移到集群中的其他服务器实战java高并发程序设计,从而提高系统可用性
通过反向代理进行负载均衡——图2 来自网络
06异步
高并发业务如果涉及到数据库操作,主要压力在数据库服务器上。 虽然采用了主从分离,但是数据库操作都是在主库上进行的。 单个数据库服务器连接池允许的最大连接数是有限制的。 的
当连接数达到最大值后,其他需要连接数据操作的请求需要等待一个空闲连接,这样在并发高的时候很多请求会出现连接超时
那么对于这样一个高并发的业务我们应该如何设计开发方案来降低数据库服务器的压力呢?
07缓存
高并发的业务接口大部分是查询业务数据,比如:商品列表、商品信息、用户信息、红包信息等,这些数据不经常变化,持久化在数据库中
高并发情况下,直接连接从库进行查询操作,多台从库服务器无法承受如此大量的连接请求(前面说了单台数据库服务器允许的最大连接数是有限制的)
那么我们如何设计这样一个高并发的业务接口呢?
08 服务至上
采用面向服务的思想,将核心业务或通用业务功能分离成服务独立部署,功能以对外接口的形式提供。
最理想的设计是将一个复杂的系统拆分成多个服务,这些服务共同构成了系统的业务。 优点:松散耦合、高可用性、高扩展性、易维护。
通过面向服务的设计,独立的服务器部署,负载均衡,数据库集群,服务可以支持更高的并发
09 冗余、自动化
当高并发业务所在的服务器宕机时,需要一个备份服务器来快速替代。 当应用服务器压力较大时,可以快速将机器加入集群,所以我们需要一台可以随时待命的备份机。 最理想的方式是自动监控服务器资源消耗并发出告警,自动切换降级方案,自动执行服务器更换和添加操作。 自动化可以降低人工操作的成本,可以快速操作,避免人工操作。 错误。
通过GitLab事件,我们应该反思,有备份数据不代表万无一失。 我们需要确保高可用性。 首先,备份是否正常,备份数据是否可用,需要我们进行定期巡检或自动化监控。 其他包括:如何避免操作中的人为错误。 (不过gitlab在事件中的开放态度和积极的处理方式还是值得学习的)
10 总结
高并发架构是一个不断进化的过程。 筑三尺冰窟非一日之功,修万里长城非一日之功。
奠定良好的基础设施以方便未来的扩展是非常重要的。