缓存的主要目的是降低数据库的读写压力,是维护大型网站稳定运行必不可少的优化手段之一,下面,结合我近段时间的工作经验,谈谈我对缓存设计的一些想法:
缓存主要分为页面缓存和数据缓存:
页面缓存
分为整体缓存和局部缓存
优点:
- 实现简单
- 能有效降低数据库的查询压力
缺点:
- 一个网页的各个区域的内容更新频率及对实时性的要求不一样,结果为了迁就更新频率的区域,要让整个页面都跟着更新,导致性能的浪费.
- 局部缓存能解决上一个缺点,但如果页面区域过多,维护这么多个区域的更新策略将是件痛苦的事
- 只能缓存最终生成的HTML,一些动态数据无法缓存,如用户登录后的session
- 只能减轻数据的读取压力,无法降低写入的压力
综合考虑上面的优缺点,将页面缓存在memcached里面显得意义不大,我决定将页面缓存主要通过生成静态文本来实现,而数据缓存则用memcached来实现.
数据缓存
memcached使用key-value来存储数据, 通过简单的get/set方法即可实现缓存的读取/写入,并且可以针对每个缓存项设置数据过期时间.
读取缓存
需要读取缓存的数据,只需从数据库取出并将其封装在一个对象里,再将该对象存入memcached即可实现数据的缓存,从而有效地降低数据库的读取压力.
写入缓存
有些数据写入很频繁(如页面的访问量统计),这时就可以将待更新的数据先放入memcached中,等累积到一定程度后再一次性写入数据库,就拿访问量统计来说,可以每访问1000次后将数据写回数据库一次,从而有效降低数据库的写入压力,并且,memcached提供了原子加法,能有效解决线程安全上面的问题.
分布式缓存
当网站规模变大,势必要增加多台memcached服务器,那么,如何有效地规范数据的缓存方案呢?
一种方案是根据业务规则来区分,不同的业务放在不同的服务器里,不过这种方案很难保证压力的均衡,并且很难扩展.
另一种方案是用类似于”取模”的方法来实现.可以将键值经过特定的算法运算后,对N取模,余数便是最终要存入的memcached服务器的编号.其中,N表示服务器的数量,以后要扩展,只需把N做相应的增加即可.