应用服务器的性能优化,是网站开发最复杂,变化最多的地方。优化的手段,主要有:缓存、集群、异步等等。从今天起,我们就来讲讲缓存。
首先,我们来看几个例子:
1、淘宝卖家浏览的商品集中在少部分 成交数多、评价良好的商品上;
2、百度搜索关键词集中在少部分热门词汇上;
3、只有经常登录的用户才会发微博、看微博,而这部分用户也只占总用户数目的一小部分。
像上面的几种情况,就非常适合我们使用缓存。
网站的访问特点与现实世界的财富分配一样,遵循二八定律:80%的业务访问集中在20%的数据上。
既然大部分业务访问集中在一小部分数据上,那么如果把这一小部分数据缓存在内存中,就可以减少数据库的访问压力,提高整个网站的数据访问速度。
缓存主要用来存放读写比很高、很少变化的数据。如商品的类别信息、热门词的搜索列表信息、热门商品信息等等。
应用程序读取数据时,先到缓存中读取,如果取不到或者数据已失效,再访问数据库,并将说几句写入缓存。
缓存,是指将数据存储在相对较高访问速度的存储介质中,以供系统处理。
一方面缓存访问速度快,可以减少数据访问的时间,另一方面如果缓存的数据是经过计算处理得到的,那么被缓存的数据无需重复计算即可直接得到,因此缓存还起到了减少计算时间的作用。
我们应该都写过这样的程序,在一个类中,我们声明一个静态的map,每次取值时,都是根据key去map里拿值,如果没有我们再去数据库里读取,然后将读上来的数据放在map里面,以供下次使用。
上面讲的这个小程序,其实就是缓存的基本原理。缓存,在java中无处不在。每一个中间件中,几乎都有缓存:hibernate、mybatis中的一级缓存、二级缓存以及查询缓存,Spring、struts源代码中都有缓存。下面我们就对这些缓存进行一个分类。
1、CDN
2、反向代理
3、本地缓存
4、分布式缓存
1、CDN
首先,我们来介绍一下CDN。
CDN,全称是Content Delivery Network,内容分发网络,它的作用是:将数据部署在距离用户最近的网络服务商,用户的网络请求总是先打达他的网络服务商,在这里缓存网站的一些静态资源,就可以就近以最快的速度返回给用户。静态资源,如图片、文件、css、script脚本、静态网页等等。
我们都可以直接租用电信、移动、联通等的机房,将静态资源放在租用的机房里面,提高访问速度。
2、反向代理
反向代理,属于前端架构的一部分。用于请求,最先访问到的就是反向代理服务器,这里缓存网站的静态资源,无需将请求继续转发给应用服务器,就能直接返给用户。
当动态内容有变化时,通知内部通知机制,通知反向代理缓存失效。反向代理会重新加载最新的动态内容再次缓存起来。
一般,中小型网站使用的nginx,就能起到反向代理的作用。
3、本地缓存
本地缓存,应用服务器本地缓存着的热点数据。本地缓存的好处就是应用程序可以直接访问内存中的数据,而无需访问数据库。这种缓存,就像我在上面举的那个map的例子。应用服务器直接从本机上读取数据,不用走网络和IO,所以这种访问速度会非常快。而它的缺点就是:会出现缓存与应用服务器争用内存的情况,内存的大小,会成为系统的瓶颈。
4、分布式缓存
通过分布式缓存服务器集群,将缓存数据分布到集群、多台服务器上,可在一定程度上改善缓存的可用性。当一台缓存服务器宕机时,只有部分缓存数据丢失,重新从数据库加载这部分数据,不会对数据库产生很大的影响,真正起到分摊数据库压力的作用。
分布式缓存服务器的集群,与应用服务器集群不同。应用服务器集群是在所有服务器上部署相同的应用,起到分摊应用服务器访问压力的作用。
而分布式缓存服务器集群中,不同的服务器中缓存的数据各不相同,缓存访问请求不可以在缓存服务器集群中的任意一台处理,必须先找到缓存有需要数据的服务器,然后才能访问。
应用
其实,缓存的技术使用,是很简单的。只要有一定SQL基础的童鞋,使用缓存上手很快的。
然后,缓存的应用难点在于:需要程序员去辨别什么时候,使用缓存。下面,我准备了几个例子,供大家参考:
例子一:新浪的缓存架构
由于微博频繁刷新,新浪微博使用多级缓存策略,热门微博和明星用户的微博,缓存在所有微博的服务器上(即本地缓存),实现高速访问;在线用户的微博和近期微博缓存在分布式缓存集群中,分摊数据库的访问压力。微博中常见的刷微博操作,几乎全是缓存访问操作。
例子二:维基百科后台性能优化
热点特别集中的数据,直接缓存到应用服务器的本地缓存中,多台应用服务器重复缓存、数据量小、读取频率高;缓存数据内容,尽量使应用服务器可直接使用的格式,如HTML格式,减少应用服务器从缓存获取数据后,解析构造数据的代价;使用分布式缓存服务器集群存储session对象。
例子三:我们公司的缓存应用
使用分布式缓存Memcache集群,存储session对象。短信验证码、产品详情、订单详情等都存储在分布式缓存中。
将一些结构不规则,展示性的信息,存储在Mongodb中;将定时任务,一些库存操作的事件信息、快照,存储在Mongodb中。