并发量面试小结

来源:互联网 发布:网线传文件软件 编辑:程序博客网 时间:2024/05/16 13:04

并发量面试小结

  根据之前面试的血泪史,除了功能以外,系统的性能也是面试官很喜欢发难的地方。由于平时在学校做的项目没有多少访问量,因此难以接触到大量并发请求达到系统性能瓶颈的问题。为了准备面试,也为了开发出性能更优化的系统,我最近查阅了一些资料,现将相关内容总结如下:

1、代码优化

  一个系统最基础的部分就是一行一行代码,如果我们的每一行代码都优化到极致,那么系统的性能想必也差不到哪去。可现实是,我们在编程时为了赶在DeadLine前完工,往往过多地关注如何实现系统的功能,而非性能。这也就给我们的系统埋下了性能隐患。

  在代码层面上,第一个要点就是编程语言的选择。每种语言都并非完美但又各有所长,比如对于计算密集型的任务,我偏向于选择C/C++来实现,比如底层的算法,图像处理算法等;如果要编写一个Web系统,那我可能选择Java或Python等等;如果要在Web系统中处理大量计算,那么我可能考虑利用Java调C的方式提升效率,比如采用JNI等。当然,语言只是一个部分,一般项目中使用的语言都是固定的。

  算法的优化是代码优化的重要一环,毕竟O(n^2)的时间复杂度和O(1)时间复杂度相差好多。这就要求我们掌握算法和数据结构的基础知识,如排序、查找、链表、树等等。

  除了上述内容外,当涉及到具体的语言时,有一些需要注意的地方,以Java为例:

  (1)、避免频繁地new对象,在一些情况下,可以使用单例模式解决我们的问题。比如,读取系统中的摄像头时,我们就可以使用单例模式,只用一个对象负责摄像头的读取。另外,在使用单例模式时,尽量使用饿汉模式(急切模式)

  (2)、尽量减少使用”+”连接字符串,这一条无论对java还是python都适用。因为每次使用“+”都会创建一个新的字符串,当字符串数量很大时,这就是一个耗时的操作了。在java中,我们可以使用StringBuilder(非线程安全)或 StringBuffer(线程安全)。在单线程时,建议使用StringBuilder,由于避免了同步操作,因此理论上比StringBuffer快。在python中,我们可以使用join连接字符串。

  (3)、ArrayList、LinkedList的选用。在我们不知道容量的情况下,或者经常进行插入和删除操作,尽量使用LinkedList,因为ArrayList的扩容需要复制数组,是一个耗时的操作。类似的容器使用小技巧还有很多,合理地使用容器能够提高程序的性能。

  (4)、合理使用多线程与多进程。
  java多线程 请见 http://blog.csdn.net/u010429424/article/details/76283778
  python多线程 请见 http://blog.csdn.net/u010429424/article/details/76100149
  python多进程 请见 http://blog.csdn.net/u010429424/article/details/76147368

  一般计算密集型任务适合使用多线程,而I/O密集型任务适合使用多进程。根据我的项目经历,使用python向arduino发送串口数据,在使用多进程后,性能提高约45%。(由20秒发送200条数据,提升至9秒200条)。因此,合理地使用多线程和多进程,也是提高系统性能的重要方式之一。

注:看过一个资料,上面说Apache早期采用多进程的方案,而IIS早期采用多线程的方案。

  (5)、位运算替代乘除法。

  位运算的速度比乘除法要快很多,所以能用位运算的地方就用位运算。比如: 整型除以2,就可以替换为右移1位

2、静态html

  把经常被用户访问的页面生成静态的html页面,这样就避免了用户每一次访问,服务器都要重新生成一个html页面。同时,对于那些更新频率很小的页面,也可以使用静态html,避免大量地访问数据库请求。

以下引自百度百科:

很多大型网站,进去的时候看它很复杂的页面,但是加载也没有耗费多长时间,除了其它必要原因以外,我认为静态化也是其中必需考虑的技术之一。她先于用户获取资源或数据库数据进而通过静态化处理,生成静态页面,所有人都访问这一个静态页面,而静态化处理的页面本身的访问速度要较动态页面快很多倍,因此程序性能会有大大的提升。总之静态化在页面上的体现为:访问速度加快,用户体验性明显提升;在后台体现为:访问脱离数据库,减轻了数据库访问压力。

3、静态资源分离部署与压缩

  对于web系统来讲,图片往往是消耗资源和带宽的大头。我曾经做过的一个图像处理的app项目。在这个项目中,服务器上保存大量的图片,客户端向服务器发送get请求来获取到服务器上的图片。为了解决图片加载慢,浪费用户流量的问题,我通过nginx静态资源分离部署、图片压缩、和客户端缓存的方式,缓解了这一问题。(当然,我的解决策略还比较粗糙~~)

(1) nginx静态资源分离部署

在nginx的配置文件中,加入location配置,定义的静态资源直接从 nginx读取。

server {    ...    # Django mdedia 静态资源分离部署    location /media {        alias /home/workspace/GWS/media; # 图片静态文件的目录,如.jpg, .png等    }    location /static {        alias /home/workspace/GWS/static; # 静态文件的目录,包括css、js、bootstrap等    }    ...}

(2) 图片压缩与页面压缩

  比如:尽量使用.jpg代替.png,因为.jpg采用了压缩算法,在图片失真允许范围内,较小图片占用的空间。另外,在一些地方无需使用高清图,完全可以使用缩略图替代。

  在Nginx中开启gzip压缩页面,可以大幅提高页面的加载速度。

http {    ...    ##    # Gzip Settings      ##    gzip on;              # 开启gzip    gzip_disable "msie6"; # ie6以上    gzip_min_length 1k;   # 大于1k才压缩    gzip_vary off;    # gzip_proxied any;    gzip_comp_level 6;    # 压缩级别[1-10],数字越大压缩效果越好,但是时间越长,占用CPU越多    gzip_buffers 16 8k;   # 缓存    # gzip_http_version 1.1;    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript image/jpeg; # 支持压缩的文件类型    ...}

(3) 客户端缓存见下文

4、缓存与Redis

  在上文中,我为了优化图片的加载速度,同时减少用户流量的开销,使用了客户端缓存的设计。说白了,就是将用户经常访问的图像,或最近一段时间内访问的图像,存储在客户端本地的文件中,这样当用户再次访问该图片时,就可以直接从本地获取,不用再向服务器发送请求了。

  另外,就是可以使用Redis做缓存

以下内容引自百度百科:

redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

Redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客户端,使用很方便。

5、异步加载Ajax

  ajax想必都用过,它最主要的特点就是实现页面的“无刷新”显示

以下内容引自百度百科:

AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML),是指一种用于创建快速动态网页的技术。
传统的网页(不使用 AJAX)如果需要更新内容,必须重载整个网页页面。而AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页。通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

6、服务器集群

  一个系统,除了软件就是硬件,当一台服务器不能满足高并发访问时,就需要多台服务器配合完成。面对大流量和高并发的问题,最好的方式就是增加硬件的投入,比如阿里天猫双11、腾讯支援1000台服务器给滴滴,就是活生生的例子。

7、数据库优化

  数据库的访问性能是制约系统性能的一个瓶颈,尤其当数据量显著增大时,这一问题就会更加突出。关于数据优化的资料有很多,总结起来如下:

  (1)、对经常被查询的字段建立索引
  (2)、优化查询,尽量避免扫描全表
  (3)、在查询语句中,尽量少使用函数操作
  (4)、update尽量只改动必要的字段,而非update全部字段
  (5)、join操作要慎用

  具体可以参考:
  http://database.51cto.com/art/201407/445934.htm

这里写图片描述

原创粉丝点击