您的位置:首页 > 其它

一个大型高并发系统的性能调优会涉及到什么?

2017-11-12 00:07 399 查看
现在一个系统的性能不单单涉及到软件系统本身,还要涉及到使用的框架性能的优劣,数据库性能的优劣,硬件设施的优劣。所以对于一个系统性能的优化,不仅涉及到项目所建立在的那个项目的软件系统,而且还涉及到数据库,硬件,操作系统,中间件,网络,并发数据量等各个方面的性能调优。

1、硬件设施

1. 服务器等硬件条件

CPU:它的每秒的运算次数

内存:内存容量与读写速率

磁盘:磁盘的空间大小和读写速率

虚拟内存需要特殊格式的磁盘空间作为内存在磁盘上的外部磁盘上的周转空间,可以将内存中不用的数据转移到磁盘上。

I/O:通过接口数的增加提高吞吐量

2. 硬件的整合策略

集群模式:提供大量服务器,每个服务器配备多个CPU等方式

磁盘阵列:提高超大容量的磁盘空间,

2、网络

1. 带宽

2. 服务端与客户端/浏览器端的网速

两端的网速同样重要。对于国内网速慢的,尤其是手机这样的浏览器端访问,网速太慢,对性能也是一种损耗。因为服务端可能因为等待时间过长而重复操作,可能连接失败,数据中断、丢失。

3. 分布式访问:通过命令将任务均衡分配到每个可用的服务器上,提高效率

3、操作系统:可以更好的调用主机的硬件空间,提高处理能力、响应能力

1. 进程管理

2. 内存管理

3. 文件系统

4. 驱动程序

4、并发用户数

并发用户数:在同一时刻与服务器进行了交互的在线用户数量。这些用户的最大特征是和服务器产生了交互,这种交互既可以是单向的传输数据,也可以是双向的传送数据。

1. 负载均衡

2. 数据库集群

就是利用至少两台或者多台数据库服务器,构成一个虚拟单一数据库逻辑映像,像单数据库系统那样,向客户端提供透明的数据服务。

3. 库表散列

采用Hash算法把数据分散到各个分表中, 这样IO更加均衡。

4. 图片服务器分离

大家知道,对于Web服务器来说,不管是Apache、IIS还是其他容器,图片是最消耗资源的,于是我们有必要将图片与页面进行分离,这是基本上大型网站都会采用的策略,他们都有独立的图片服务器,甚至很多台图片服务器。

5. 镜像

镜像是大型网站常采用的提高性能和数据安全性的方式,镜像的技术可以解决不同网络接入商和地域带来的用户访问速度差异,比如ChinaNet和EduNet之间的差异就促使了很多网站在教育网内搭建镜像站点,数据进行定时更新或者实时更新。

6. 缓存

7. HTML静态化

8. CDN加速技术

5、系统积累的数据量

1. 数据库的存储能力

2. 数据库查询速率

  涉及到索引、所涉及内容的数据量、查询内容的长短

3. 大数据的数据分析、分类、挖掘等

6、中间件

1.在系统与数据库之间提供高速高效缓存

比如网站系统与数据库之间的Redis、memCache、MongDB,他们将数据缓存到内存中,提供数据的获取能力,从而提高性能,提高响应的速率

比如Spring与Redis中间的dubbo,进一步优化数据缓存

7、数据库的优化

1. 表与表之间关系越简单越好

数据库三大范式很好,但是对于一个高并发的系统来说,数据库中数据的关系越简单,获取越快速,对于系统性能消耗越低。

2. 索引提升性能

3. SQL语句优化

实质就是在结果正确的前提下,用优化器可以识别的语句,充分利用索引来减少表扫描的I/O次数,尽量避免表搜索的发生。优化的目的就是将性能低下的SQL语句转换成目的相同的、性能优异的SQL语句,使数据查找的路径最简化,并尽量保持处理器时间和I/O时间的平衡。通常分为以下几个步骤:1)查找有问题的SQL语句。优化有问题的sql语句能显著提高数据库性能。寻找的方法有:搜集统计数据,oracle中可以通过DBMSSTATS包或ANALYZE命令,前者

可用于搜集有关链接数据行的统计数据,簇的数据情况只能使用ANALYEZ命令获得,其相关语法为ANALYEZE CLUSTERCluste_name ComputerSTATISTICS,对于其它情况可以使用DBMS_SATS包,语法为:execDBMS_SATS.gather_table_stats(‘owname’,’tablename’,

’partnmae’);利用SQLTrace工具分析SQL语句。通过命令ALTER SESSION SET SQL_TRACE=TRUE会话激活SQL_TRACE,oracle就会在udump管理区创建跟踪文件,从而可以了解如解析、执行和返回数据的次数、CPU时间和执行时间、物理读和逻辑读操作次数、库缓冲区命中率等参数;通过oracleEnterpriseManager Console、Oracle Diagnostics Pack等图形性能工具能够很快地获取到数据库缓冲区命中率、CPU利用率、运行时内存等重要的数据库性能指标信息,并将它们以GUI表格形式和曲线图形式显示出来;2)建立合适的SQL语句。参照原则如下:建立“适当”的索引,使用索引的根本目的就是为了提高查询效率,但索引也不是越多越好,使用索引时应遵循相应的原则。此外,为了降低I/O竞争,索引不应与用户表空间建在同一磁盘上;避免使用耗费资源的操作如DSJTNITC、UNION、GROUP
BY、ORDERBY等关键字,因为他们会启动SQL引擎执行耗费资源的排序功能

4. 数据库应用系统参数优化

(1)调整服务器内存分配

(2)调整磁盘IPO

(3)调整资源竞争

5. 优化数据库物理结构

(1)优化设置控制文件的个数,位置及其备份

建议CONTROL_ FILE初始化参数中指定多个文件应大于2,并将控制文件镜像到不同位置,并要把这些控制文件备份到安全的磁盘中。

(2)优化设计表空间,数据文件的大小及位置

(3)优化设计重演日志文件

(4)数据库集群

集群是一组相互独立的、通过高速网络互联的计算机,它们构成了一个组,并以单一系统的模式加以管理.数据库集群系统是由多个共享一个数据库的有独立操作系统的服务器组成[6]

Oracle 10g RAC是一种基于网格服务的数据库集群系统架构,它具有每一层计算堆栈上的虚拟化、根据策略和动态需求来分配工作和资源、集中资源以提高利用率、能自我调整和修补、可统一管理和供应的特点

8、系统编程架构上的优化

1. 工厂模式等设计模式的运用

2. 软编码

   将系统配置的参数写到配置文件里或者xml中

3. 面向接口编程

4. 借助框架实现优化

比如借助SSM(Spring+SpringMVC+Mybatis)架构实现软编码,面向接口编程。但是框架也要它自身的限制、缺点。框架集成的东西多,对系统也是一种性能上的伤害。

5. mysql大数据分页查询优化

6. 尽量使用缓存

9、程序具体细节的优化

代码优化的工具推荐:lombok

lombok是一款可以精减java代码、提升开发人员生产效率的辅助工具,利用注解在编译期自动生成setter/getter/toString()/constructor之类的代码。减少了代码行数,不会看到一大堆的get、set干扰视线 

1. 减少try/catch的使用

2. 对于常量字符串,用'string' 代替 'stringbuffer' 

3. 不要在循环体中实例化变量

   在循环体中实例化临时变量将会增加内存消耗

4. 尽量使用final修饰符 

5. 尽量重用对象

6. 尽量使用局部变量

7. 在java+Oracle的应用系统开发中

   java中内嵌的SQL语言应尽量使用大写形式,以减少Oracle解析器的解析负担。

8. I/O流、文件流、Servlet等及时关闭

java编程过程中,进行数据库连接,I/O流操作,在使用完毕后,及时关闭以释放资源。因为对这些大对象的操作会造成系统大的开销。

9. 慎用异常,异常对性能不利

10. 采用在需要的时候才开始创建的策略

11. 通过StringBuffer的构造函数来设定他的初始化容量,可以明显提升性能

12. 当复制大量数据时,使用 System.arraycopy()

13. 代码重构,增加代码的可读性

14. 不用new关键字创建对象的实例。 

用 new关键词创建类的实例时,构造函数链中的所有构造函数都会被自动调用。但如果一个对象实现了Cloneable接口,我们可以调用她的clone() 方法。clone()方法不会调用任何类构造函数。 

下面是Factory模式的一个典型实现。 

public static Credit getNewCredit()

{

    return new Credit();

}

改进后的代码使用clone() 方法, 

private static Credit BaseCredit = new Credit();

public static Credit getNewCredit()

{

    return (Credit)BaseCredit.clone();

}

15. 乘除法如果可以使用位移,应尽量使用位移,但最好加上注释,方便理解

16. 不要将数组声明为:public static final

17. HaspMap的遍历

Map<String, String[]> paraMap = new HashMap<String, String[]>();

for( Entry<String, String[]> entry : paraMap.entrySet() )

{

    String appFieldDefId = entry.getKey();

    String[] values = entry.getValue();

}

利用散列值取出相应的Entry做比较得到结果,取得entry的值之后直接取key和 value。

18. 分清何时用array(数组)和ArrayList

array 数组效率最高,但容量固定,无法动态改变,ArrayList容量可以动态增长,但牺牲了效率。

19. 单线程应尽量使用 HashMap, ArrayList

除非必要,否则不推荐使用HashTable,Vector,她们使用了同步机制,而降低了性能。

20. StringBuffer和StringBuilder,最好使用前者

StringBuffer,StringBuilder 的区别在于:java.lang.StringBuffer 线程安全的可变字符序列。一个类似于String的字符串缓冲区,但不能修改。StringBuilder与该类相比,通常应该优先使用 StringBuilder类,因为她支持所有相同的操作,但由于她不执行同步,所以速度更快。为了获得更好的性能,在构造StringBuffer或 StringBuilder时应尽量指定她的容量。当然如果不超过16个字符时就不用了。 

相同情况下,使用StringBuilder比使用 StringBuffer仅能获得10%~15%的性能提升,但却要冒多线程不安全的风险。综合考虑还是建议使用StringBuffer。

21. 尽量使用基本数据类型代替对象

22. 用简单的数值计算代替复杂的函数计算,比如查表方式解决三角函数问题

23. 尽量避免使用二维、三维数组

    二维数组比一维数组占用更多的内存空间,大概是10倍计算

24. 数据库查询尽可能不使用嵌套查询

数据库读取整张表的全部数据很快,但有条件的查询就要耗时30-50MS,大家做这方面的时候要注意,尽量少用,尤其是嵌套查找!

25. 循环最好三层以内,避免写复杂的表达式

在不做编译优化的情况下,在循环中,循环条件会被反复计算,如果不使用复杂表达式,而使循环条件值不变的话,程序将会运行的更快。 

例子: 

import java.util.vector;

class cel {

    void method (vector vector) {

        for (int i = 0; i < vector.size (); i++)  // violation

            ; // ...

    }

}

更正: 

class cel_fixed {

    void method (vector vector) {

        int size = vector.size ()

        for (int i = 0; i < size; i++)

            ; // ...

    }

}

参考文章网址:

1. 影响软件性能的因素
http://www.voidcn.com/article/p-ajptbevb-xz.html
2. 大型网站优化之高性能
http://www.jianshu.com/p/611ad4efdf30
3. 如何解决高并发问题
http://blog.csdn.net/qq_35522169/article/details/52572611
4. java程序性能优化
https://www.cnblogs.com/chinafine/articles/1787118.html
5. java系统性能调优
https://www.cnblogs.com/swp520lmg/articles/5607180.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: