应用服务器就是处理网站业务的服务器,网站的业务代码都部署在这里,是网站开发最复杂,变换最多的地方,优化手段主要有缓存、集群、异步等。
1. 分布式缓存
网站性能优化第一定律:优先考虑使用缓存优化性能。 在整个网站应用中,缓存几乎无处不在,既存在于浏览器,也存在于应用服务器和数据库服务器;既可以对数据缓存,也可以对文件缓存,还可以对页面片段缓存。合理使用缓存,对网站性能优化意义重大。
1.1 缓存的基本原理
缓存指将数据存储在相对较高访问速度的存储介质中,以供系统处理。一方面缓存访问速度快,可以减少数据访问的时间,另一方面如果缓存的数据是经过计算处理得到的,那么被缓存的数据无需重复计算即可直接使用,因此还起到减少计算时间的作用。
缓存的本质是一个内存hash表,数据存储以一对Key、Value的形式存储在内存hash表中。Hash表数据读写的时间复杂度为O(1)。计算KV对中Key的HashCode对应的Hash表索引,可快速访问Hash表中的数据。
缓存主要用来存放那些读写比很高、很少变化的数据。应用程序读取数据时,先到缓存中读取,如果读取不到或者数据已失效,再访问数据库,并将数据写入缓存,如下图所示:
网站数据访问通常遵循二八定律,即80%的访问落在20%的数据上,因此利用Hash表和内存的高速访问特性,将这20%的数据缓存起来,可很好地改善系统性能,提高数据读取速度,降低存储访问压力。
1.2 合理使用缓存
使用缓存对提高系统性能有很多好处,但是不合理使用缓存非但不能提高系统的性能,还会成为系统的累赘。实践中,缓存滥用的情景屡见不鲜:过分依赖低可用的缓存系统、不恰当地使用缓存的数据访问特性等。
频繁修改的数据
如果缓存中保存的是频繁修改的数据,就会出现数据写入缓存后,应用还来不及读取缓存,数据就已经失效的情况。一般说来,数据的读写比在2:1以上,缓存才有意义。实践中,这个读写比通常非常高,比如新浪微博的热门微博,缓存以后可能会被读取数百万次。
没有热点的访问
缓存使用内存作为存储,内存资源宝贵而且有限,不可能将所有数据都缓存起来,只能将最新访问的数据缓存起来,而将历史数据清理出缓存。如果应用系统访问数据没有热点,不遵循二八定律,即大部分数据访问并没有集中在小部分数据上,那么缓存就没有意义,因为大部分数据还没有被再次访问就已经被挤出缓存了。
数据不一致与脏读
一般会对缓存的数据设置失效时间,一旦超过失效时间,就要从数据库中重新加载。因此应用要容忍一定时间的数据不一致,在互联网应用中,这种延迟通常是可以接受的,但是具体应用仍需慎重对待。还有一种策略是数据更新时立即更新缓存,不过这会带来更多系统开销和事务一致性的问题。
缓存可用性
缓存是为提高数据读取性能的,缓存数据丢失或者缓存不可用不会影响到应用程序的处理—它可以直接从数据库获取数据。但是随着业务的发展,缓存会承担大部分数据访问的压力,数据库已经习惯了有缓存的日子,所以当缓存服务崩溃时,数据库会因为完全不能承受如此大的压力而宕机,进而导致整个网站不可用。这种情况被称作缓存雪崩,发生这种故障,甚至不能简单地重启缓存服务器和数据库服务器来恢复网站访问。
通过分布式缓存服务器集群,将缓存数据分布到集群多台服务器上可在一定程度上改善缓存的可用性。当一台缓存服务器宕机的时候,只有部分缓存数据丢失,重新从数据库加载这部分数据不会对数据库产生很大影响。
缓存预热
缓存中存放的是热点数据,热点数据又是缓存系统利用LRU(最近最久未用算法)对不断访问的数据筛选淘汰出来的,这个过程需要花费较长的时间。新启动的缓存系统如果没有任何数据,在重建缓存数据的过程中,系统的性能和数据库负载都不太好,那么最好在缓存系统启动时就把热点数据加载好,这个缓存预加载手段叫做缓存预热。
缓存穿透
如果因为不恰当地业务、或者恶意攻击持续高并发地请求某个不存在的数据,由于缓存没有保存该数据,所有的请求都会落到数据库上,会对数据库造成很大压力,甚至崩溃。一个简单地对策就是将不存在的数据也缓存起来(其value值为null)。
2. 异步操作
使用消息队列将调用异步化,可改善网站的扩展性,同时可以改善网站系统的性能。
在不使用消息队列的情况下,用户的请求数据直接写入数据库,在高并发地情况下,会对数据库造成巨大的压力,同时也使得响应延迟加剧。在使用消息队列后,用户请求的数据发送给消息队列后立即返回,再由消息队列的消费者进程(通常该进程独立部署在专门的服务器集群上)从消息队列中获取数据,异步写入数据库。由于消息队列服务器处理速度远快于数据库,因此用户的响应延迟可得到有效改善。
消息队列具有很好地削峰作用—即通过异步处理,将短时间高并发产生的事务消息存储在消息队列中,从而削平高峰期的并发事务。需要注意的是,由于数据写入消息队列后立即返回给用户,数据在后续的业务校验、写入数据库等操作可能失败,因此在使用消息队列进行业务异步处理后,需要适当修改业务流程进行配合,如订单提交后,订单数据写入消息队列,不能立即返回用户订单提交成功,需要在消息队列的订单消费者进程真正处理完该订单,甚至商品出库后,再通过电子邮件通知用户订单成功,以免交易纠纷。
3. 使用集群
在网站高并发访问的场景下,使用负载均衡技术为一个应用构建一个由多台服务器组成的服务器集群,将并发访问请求分发到多台服务器上处理,避免单一服务器因负载压力过大而响应缓慢,使用户请求具有更好的响应延迟特性。