论坛首页 Java企业应用论坛

漫谈应用缓存的命中率问题

浏览 25581 次
该帖已经被评为良好帖
作者 正文
   发表时间:2007-05-09  
这篇文章源自于:

http://www.iteye.com/topic/77195

其中很多人谈到了缓存命中率的问题,应用缓存的命中率取决于很多的因素:

1、应用场景
是OLTP还是OLAP应用,即使是OLTP,也要看访问的频度,一个极少被访问到的缓存等于没有什么效果。一般来说,互联网网站是非常适合缓存应用的场景。

2、缓存的粒度
毫无疑问,缓存的粒度越小,命中率就越高,对象缓存是目前缓存粒度最小的,因此被命中的几率更高。举个例子来说吧:你访问当前这个页面,浏览帖子,那么对于ORM来说,需要发送n条SQL,取各自帖子user的对象。很显然,如果这个user在其他帖子里面也跟贴了,那么在访问那个帖子的时候,就可以直接从缓存里面取这个user对象了。

3、架构的设计
架构的设计对于缓存命中率也有至关重要的影响。例如你应该如何去尽量避免缓存失效的问题,如何尽量提供频繁访问数据的缓存问题,这些都是考验架构师水平的地方。再举个例子来说,对于论坛,需要记录每个topic的浏览次数,所以每次有人访问这个topic,那么topic表就要update一次,这意味着什么呢?对于topic的对象缓存是无效的,每次访问都要更新缓存。那么可以想一些办法,例如增加一个中间变量记录点击次数,每累计一定的点击,才更新一次数据库,从而减低缓存失效的频率。

4、缓存的容量和缓存的有效期
缓存太小,造成频繁的LRU,也会降低命中率,缓存的有效期太短也会造成缓存命中率下降。

所以缓存命中率问题不能一概而论,一定说命中率很低或者命中率很高。但是如果你对于缓存的掌握很精通,有意识的去调整应用的架构,去分解缓存的粒度,总是会带来很高的命中率的。

这里我可以举一个实际的案例,JavaEye2.0网站在使用对象缓存之前,通过MySQL的监控工具进行观察,在连续24小时的平均每秒发送SQL条数超过了200条,在使用对象缓存之后,连续24小时的平均每秒发送SQL条数下降到了120条左右,几乎下降了一半。

考虑到很多SQL都是分页语句,关联查询,条件查询,集合操作,都是不能被缓存的SQL,而真正能够被缓存的SQL只有根据主键查询对象和对象关联对象的查询。所以真正能够被缓存的SQL估计最多占所有SQL的60%。所以换算下来,应用缓存的命中率之高,已经相当惊人了。

不过这里要提醒的一点,有将近一半的SQL都被缓存,不意味着性能可以提升一倍。这是因为能够被缓存的都是按照主键查询单条记录的SQL,这些SQL本身即使发送到数据库,对数据库造成的压力也没有想像的那么大。真正对数据库造成庞大压力的正是那些没有索引的大表查询,和造成了全表扫描的关联查询,这些一旦涉及到全表扫描的查询,才是性能的真正杀手。当然了,不管怎么说,通过使用对象缓存,是毫无疑问可以大幅度降低数据库的负载压力的,有效提升web应用的性能的。

关于这一点,我再给出一组数据来加深大家的印象,通过使用操作系统网络工具进行统计:

JavaEye网站web server的端口每秒数据流量是2MB;
JavaEye网站的MySQL数据库端口的每秒数据流量是1.2MB;
而网站的memcached的端口每秒的数据流量高达5MB。



   发表时间:2007-05-09  
的确收益颇多.
ms对象缓存在多数情况下是个不错的选择.

说到对象的话,题外话:
http://www.theserverside.com/news/thread.tss?thread_id=45306
0 请登录后投票
   发表时间:2007-05-09  
认真看了,读懂了你的意思!但不明白具体该怎么做,比如我在一个Struts + Spring + iBatis + MySql的项目中怎么实现大侠您说的对象缓存?Web容器为TomCat ,,,,,
0 请登录后投票
   发表时间:2007-05-09  
robbin 写道

考虑到很多SQL都是分页语句,关联查询,条件查询,集合操作,都是不能被缓存的SQL,而真正能够被缓存的SQL只有根据主键查询对象和对象关联对象的查询。所以真正能够被缓存的SQL估计最多占所有SQL的60%。所以换算下来,应用缓存的命中率之高,已经相当惊人了。

如果Active Record有类似Hibernate的query cache功能,在这个时候就可以体现出它的威力了,拿论坛来来作为例子,99%以上的访问都只是打开分类的第一页,最多也不会超过3页,加上Cache是非常有效的,偶们有一个应用,和论坛很类似,在加query cache之前,峰值只能支持80 hit/sec,加了以后,上升到了460 hit/sec.

另外,现在很多论坛都喜欢在帖子列表上直接显示分页,比如这样:
精华:     [Hibernate] 不做技术的奴隶
[ 分页: 1 2 3 4 5 6 7 8  ]

但是偶怀疑几乎没有人会在列表上直接点击具体的页数,都是到帖子第一页或者最后一页,然后在帖子里面再慢慢翻页的,猜想这个显示方式是很耗sql的,如果去掉这种无太大用处的页面设计,对于cache的设计也会有很好的帮助。
0 请登录后投票
   发表时间:2007-05-09  
Readonly 写道


另外,现在很多论坛都喜欢在帖子列表上直接显示分页,比如这样:
精华:     [Hibernate] 不做技术的奴隶
[ 分页: 1 2 3 4 5 6 7 8  ]

但是偶怀疑几乎没有人会在列表上直接点击具体的页数,都是到帖子第一页或者最后一页,然后在帖子里面再慢慢翻页的,猜想这个显示方式是很耗sql的,如果去掉这种无太大用处的页面设计,对于cache的设计也会有很好的帮助。


不认为这是无太大用处的功能,我就经常点中间的页数,如果第一次看这个帖子时只有4页,过了几天达到8页了,那我显然直接从第4页看起,一次一次点下一页岂不是麻烦,而且更浪费服务器资源,有时要看谁在第几页的发言当然也是直接点页数。
0 请登录后投票
   发表时间:2007-05-09  
你这样的人还是少数。
0 请登录后投票
   发表时间:2007-05-09  
对象缓存是基本的
对于很多应用,查询缓存才是最关键的
尤其对web这种列表应用
0 请登录后投票
   发表时间:2007-05-09  
janh 写道
不认为这是无太大用处的功能,我就经常点中间的页数,如果第一次看这个帖子时只有4页,过了几天达到8页了,那我显然直接从第4页看起,一次一次点下一页岂不是麻烦,而且更浪费服务器资源,有时要看谁在第几页的发言当然也是直接点页数。

偶是指不要把那么页数显示在分论坛的帖子列表中,在进入单个帖子的页面当然还是需要的。
另外,偶的小脑袋哪能记住几天前看到第几页这种OOXX的事情,还要记住谁在第几页的发言简直是@#¥%...这种大肠帖都是点开最后一页,然后依靠回复时间来找到大致位置
0 请登录后投票
   发表时间:2007-05-09  
robbin讲的都是对象缓存,想冒昧请问一下,javaeye使用了页面缓存吗?对于页面缓存,那么是算作粗粒度还是细粒度呢?这样做的也应该可以控制到比较高的命中率吧,和对象缓存相比,两者各有什么优劣,或者说两者一起使用是否能够做到比单纯的对象缓存更好呢?

在我们做过的一个web项目中,是通过模版生成伪静态页面,说它是伪静态,是因为这个页面本身也是一个模版,在生成最终页面呈现给用户时,会填入一些动态的数据,就比如这个论坛的投票数量什么的。相当于磁盘缓存了,但这个是应用服务器的本地磁盘,速度上很快,而且避免了服务器之间的网络通信。比如论坛里每个帖子的文章内容,不需要再去数据库或者缓存里取,这样是不是能减少与memcached通信的流量呢。

web应用多数都是查询大于数据操作,那么cache用于解决性能是屡试不爽,但是对于插入,更新频繁的企业应用,一般是应该从哪方面去解决的呢。

另外,想请教下对于新闻发布系统那种纯静态页面,apache有没有什么模块,可以判断静态页面是否存在,如果不存在,才给应用服务器发出请求
0 请登录后投票
   发表时间:2007-05-09  
yfmine 写道
另外,想请问一下,对于新闻发布系统那种纯静态页面,apache有没有什么模块能判断静态页面是否存在,如果不存在,才给应用服务器发出请求呢?

mod_rewrite 是可以的
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics