标签:style blog http io ar os 使用 sp strong
***{转自:缓存设计的一些思考}***
互联网架构中缓存无处不在,某厂牛人曾经说过:”缓存就像清凉油,哪里不舒服,抹一下就好了”。高品质的存储容量小,价格高;低品质存储容量大,价格低,缓存的目的就在于”扩充”高品质存储的容量。本文探讨缓存相关的一些问题。
LRU替换算法
缓存的技术点包括内存管理和替换算法。LRU是使用最多的替换算法,每次淘汰最久没有使用的元素。LRU缓存实现分为两个部分:Hash表和LRU链表,Hash表用于查找缓存中的元素,LRU链表用于淘汰。内存常以Slab的方式管理。
上图是Memcache的内存管理示意图,Memcache以Slab方式管理内存块,从系统申请1MB大小的大块内存并划分为不同大小的Chunk,不同Slab的Chunk大小依次为80字节,80 * 1.25,80 * 1.25^2, …。向Memcache中添加item时,Memcache会根据item的大小选择合适的Chunk。
Oceanbase最初也采用LRU算法,只是内存管理有些不同。Oceanbase向系统申请2MB大小的大块内存,插入item时直接追加到最后一个2MB内存块的尾部,当缓存的内存量太大需要回收时根据一定的策略整块回收2MB的内存,比如回收最近最少使用的item所在的2MB内存块。这样的做法虽然不是特别精确,但是内存管理简单,对于系统初期很有好处。
缓存锁
缓存需要操作两个数据结构:Hash表和LRU链表。多线程操作cache时需要加锁,比较直接的做法是整体加一把大锁后再操作Hash表和LRU链表。有如下的优化思路:
LIRS思想
Cache有两个问题:一个是前面提到的降低锁粒度,另一个是提高精准度,或者称为提高命中率。LRU在大多数情况下表现是不错的,但是有如下的问题:
之所以会出现上述一些比较极端的问题,是因为LRU只考虑访问时间而没有考虑访问频率,而LIRS在这方面做得比较好。LIRS将数据分为两部分:LIR(Low Inner-reference Recency)和HIR(High Inner-reference Recency),其中,LIR中的数据是热点,在较短的时间内被访问了至少两次。LIRS可以看成是一种分级思想:第一级是HIR,第二级是LIR,数据先进入到第一级,当数据在较短的时间内被访问两次时成为热点数据则进入LIR,HIR和LIR内部都采用LRU策略。这样,LIR中的数据比较稳定,解决了LRU的上述两个问题。LIRS论文中提出了一种实现方式,不过我们可以做一些变化,如可以实现两级cache,cache元素先进入第一级cache,当访问频率达到一定值(比如2)时升级到第二级,第一级和第二级均内部采用LRU进行替换。Oracle Buffer Cache中的Touch Count算法也是采用了类似的思想。
SSD与缓存
SSD发展很快,大有取代传统磁盘之势。SSD的发展是否会使得单机缓存变得毫无必要我们无从得知,目前,Memory + SSD + 磁盘的混合存储方案还是比较靠谱的。SSD使用可以有如下不同的模式:
当然,随着SSD的应用,我想减少缓存锁粒度的重要性会越来越突出。
总结&推荐资料
到目前为止,我们在SSD,缓存相关优化的工作还是比较少的。今后的一年左右时间,我们将会投入一定的精力在系统优化上,相信到时候再来总结的时候认识会更加深刻。我想,缓存相关的优化工作首先要做的是根据需求制定一个大致的评价标准,接着使用实际数据做一些实验,最终可能会同时保留两到三种实现方式或者配置略微有所不同的缓存实现。缓存相关的推荐资料如下:
[1] Touch Count Algorithm. http://youyus.com/wp-content/uploads/resource/Shallahamer%20TC4a.pdf
[2] LIRS. http://portal.acm.org/citation.cfm?id=511340
标签:style blog http io ar os 使用 sp strong
原文地址:http://www.cnblogs.com/big-xuyue/p/4100794.html