稳定高并发高性能程序设计原则简单总结

引言

高并发经常会发生在有大活跃用户量,用户高聚集的业务场景中,如:秒杀活动,定时领取红包等。

为了让业务可以流畅的运行并且给用户一个好的交互体验,我们需要根据业务场景预估达到的并发量等因素,来设计适合自己业务场景的高并发处理方案。

在工作这些年里,我有幸遇到了高并发各种坑,对如何设计高性能接口有一些经验,其实无外乎满足以下几个特点:

灵敏性 伸缩性 容错性 事件驱动/消息驱动 高性能接口设计准则

在引言里我也说了高性能设计的四个准则,现在具体对这四个准则做一些描述;

  1. 灵敏性

应用程序应该尽可能快的对请求做出响应。

如果可以在顺序获取数据和并行获取数据之间进行选择的话,为了尽快向用户返回响应,始终应该优先选择并行获取数据,可以同时请求互相没有关联的数据。当我们需要请求多个互相无关,没有依赖的数据的时候,应该考虑是否能够同时请求这些数据。

如果可能出现错误,应该立即返回,将问题通知用户,不要让用户等待直到超时。

1.1 如何设计灵敏性

缓存前置

对于一些改变不频繁的数据,应该放在分布式缓存中,例如redis,如果是一些元数据(例如,一些计数器的配置信息,变量的配置信息等)则应该启用本地缓存,简单流程如下:

如何设计高性能的接口 如果一些热点数据不大的话,建议服务启动的时候就应该提前加载到缓存中,这样可以提高服务的性能。

读写拆分部署

如果你的服务既涉及到读操作,也涉及到写操作, 应该将读写隔离部署,这样读服务的压力不会影响到写服务,写服务的压力不会影响到读服务。流程如下:

如何设计高性能的接口 当然除了按照读写进行拆分部署外,还可以按照业务进行隔离部署。

对等设计、无状态

所谓无状态是指应用服务器不保存业务的上下文信息,而仅根据每次请求提交的数据进行相应的业务逻辑处理,多个服务实例(服务器)之间完全对等,请求提交到任意服务器,处理结果是完全一样的。

不保存状态的应用给高可用的架构设计带来了巨大便利,既然服务器不保存请求的状态,那么所有的服务器完全对等,当任意一台或多台服务器宕机,请求提交给集群中的其他任意一台可用机器处理,这样对终端用户而言,请求总是能够成功的,整个系统依然可用。对于应用服务器集群,实现这种服务器可用状态实时检测、自动转移失败任务的机制就是负载均衡。

如何设计高性能的接口 DB分库分表,读写分离

对于数据层来说,如果数据量不大,db可以采用读写分离部署,对于读多写少的场景可以解决一部分压力,从而提高我们接口的响应速度,如果写的数据量和读的数据量都很大,那么就必须要对db进行分库分表外加读写分离了。

如何设计高性能的接口 2. 伸缩性

应用程序应该能够根据不同的工作负载进行伸缩扩展(尤其是通过增加计算资源来进行扩展)。为了提供伸缩性,系统应该努力消除瓶颈。

如果在虚拟机上运行内存数据库,那么添加另一个虚拟几点就可以将所有的查询请求分布到两台虚拟服务器上,将可能的吞吐量增加至原来的两倍。添加额外的节点应该能够几乎线性的提高系统的性能。

增加一个内存数据库的节点后,还可以将数据分为两半,并将其中的一半移至新的节点,这样就能够将内存容量提高至原来的两倍。添加节点应该能够几乎线性的提高内存容量。

所以一般好的接口设计是可以通过水平扩展机器来达到提升性能的,这就要求我们设计接口的时候提现无状态性。

  1. 容错性

应用程序应该考虑到错误发生的情况,并且从容的对错误情况做出响应。如果系统的某个组件发生错误,对与该组件无关的请求不应该产生任务影响。错误是难以避免的,因此应该将错误造成的影响限制在发生错误的组件之内。如果可能的话,通过对重要组件及数据的备份和冗余,这些组件发生错误时不应该对其外部行为有任何影响。

稳定性

稳定性是第一前提,如系统崩溃恢复容灾备份这些,主要是一些数据保护的机制,还有就是程序参数的校验、异常的处理、事务的回滚、程序边界的设计(合理的边界划分可以避免服务的连锁崩溃)、对账机制等,这些都是日常生活中常用的一些手段在计算机领域的体现,更详细的设计就不深入的分析了。

高并发

通过多年来对操作系统的研究,以及结合多年来各种语言的编程经验来说,高性能的程序的开发其实都是有规可循的。因为高性能的程序基本上都会面临相似的问题:如何提高并发,如何降低时间复杂度(但是并不是一味的降低,需要在空间复杂度之间做一个平衡)。

如何提高并发:在目前的大多数程序中或多或少的都会遇到并发的问题,如何设计高效的并发非常的重要,从我个人的经验来说,当遇到一个会存在并发的业务场景,我会首先整理业务场景,并根据业务场景画出简单的数据流图,根据数据流图找出相应的会并发访问修改的数据,缩小加锁的粒度(只对需要并发访问的数据进行加锁),。

然后分析数据的性质是否可以局部的并发,这种情况下就可以使用分段锁(再次减小加锁的粒度,一个比较出名的例子就是mysql的表锁、行锁机制)。

最后再分析数据的访问性质,是读多写少(大部分都是这种情况)、读少写多(日志)、还是读写频率差不多,不同的业务情况使用不同的锁,比如针对读多写少的业务来说,为了提高读的并发性可以使用读写锁;针对并发粒度较小,且并发操作的耗时很短的情况,操作系统又提出了CAS操作(乐观锁),这种操作避免了上锁和释放锁耗时的过程,进一步提高了并发性,但是只是针对特定的场景才能达到想要的性能。

当单台并发达到上限之后,就是分布式系统粉墨登场了,虽然分布式系统数据一致性会有一定的耗时,但是分布式系统的并发却有了显著的提高,一致性所带来的耗时/并发数带来的平均延迟并不大,所以能很好的满足系统的需求。

高性能

高性能的设计主要分为两个层面,一个层面是操作系统层面的,另外一个层面是业务层。

操作系统层面:尽量使用操作系统和处理器自身的高性能的指令或者是运算方式,最简单的例子是位运算,针对一些特殊的算法如果能使用位运算实现,那么尽量使用位运算实现(这在很多算法面试题中都会考的,因为位运算在很多场景都有特别切合实际的使用),还有就是合理高效的使用操作系统自身的API,如DMA之类的机制,以及有效的利用缓存之类的机制。

业务层面来说:首先需要为数据的存储设计合适的数据结构,这个也需要在空间利用率和访问复杂度之间做权衡;然后为业务中需要计算的场景设计高效的算法,算法的抽象是一个比较难的事情,算法设计需要在时间复杂度和空间复杂度中做权衡,还有就是针对算法的特性进行优化,可以参考算法设计,如果算法具有分治、动态规划这些算法的特性,那么此类算法可以采用并发机制提高算法的性能(算法设计很复杂,算法本身涉及到的很多高等数学的知识,还有就是算法的实现是否更加符合计算机的运行机制,建议多看看ACM算法设计相关书籍)如果想学习Java工程化、高性能及分布式、深入浅出。性能调优、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级架构进阶群:180705916,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值