<p >php高性能的缓存存储引擎secache</p>
<p >ShopEx前台全页缓存-存储器for ShopEx开发文档<br />
2009-12-28 09:52:43 来源: ShopEx开发团队 【大 中 小】 分享到新浪微博 分享到i贴吧<span class="Apple-converted-space"></span><br />
cachemgr决定了哪些内容被缓存,缓存多久,如何被更新,怎样判别缓存过期。缓存存储器仅仅是负责缓存如何存放,如何读取。当缓存过多时如何被自动删除,删除哪一些。</p>
<p >shopex系统默认的缓存存储器是secache。可以被替换为apc或者memcache。</p>
<p >secache的特点如下:</p>
<p >使用lru算法自动清理过期内容<span class="Apple-converted-space"></span><br />
可以安全用于多进程并发<span class="Apple-converted-space"></span><br />
最大支持1G缓存文件,性能不受文件大小影响<span class="Apple-converted-space"></span><br />
使用hash定位,读取迅速<span class="Apple-converted-space"></span><br />
secache已经被我们开源:<span class="Apple-converted-space"></span><a href="http://code.google.com/p/secache/">http://code.google.com/p/secache/</a><span class="Apple-converted-space"></span>。版权采用的是最开放的MIT Licence,大家可以随意的用在自己的系统里。</p>
<p >用法样例</p>
<p >require('../secache/secache.php');<br />
$cache = new secache;<br />
$cache->workat('cachedata');<br />
$key = md5('test'); //必须自己做hash,前4位是16进制0-f,最长32位。<br />
$value = '值数据'; //必须是字符串<br />
$cache->store($key,$value);<br />
if($cache->fetch($key,$return)){<br />
echo '<br />
'.$key.'=>'.$return.'';<br />
}else{<br />
echo '<br />
Data get failed! '.$key.'';<br />
}<br />
基于性能考虑,几点约束:</p>
<p >键需要自己做hash处理,最长32位.<span class="Apple-converted-space"></span><br />
值必须是字符串。如果要存对象,请自己serialize<span class="Apple-converted-space"></span><br />
下面详细说明secache的实现原理</p>
<p >secache是一个采用拉链法的hash结构。整个文件分成2个主要部分。</p>
<p >结构信息区<span class="Apple-converted-space"></span><br />
保留空间 20字节,放置一个防止文件被下载<span class="Apple-converted-space"></span><br />
保留空间 20字节,放置文件的版本信息,最大容量<span class="Apple-converted-space"></span><br />
20字节保留区域<span class="Apple-converted-space"></span><br />
结构信息 16种slab结构,每个需要24字节,占用空间:24*16=384字节<span class="Apple-converted-space"></span><br />
索引信息区<span class="Apple-converted-space"></span><br />
索引计数器数据 40-44<span class="Apple-converted-space"></span><br />
数据最大空间指针 44-48<span class="Apple-converted-space"></span><br />
空闲链表入口地址 48-52<span class="Apple-converted-space"></span><br />
hash索引入口地址 (16^4)*4 = 256k<span class="Apple-converted-space"></span><br />
数据区(混杂)<span class="Apple-converted-space"></span><br />
索引链表<span class="Apple-converted-space"></span><br />
数据链表<span class="Apple-converted-space"></span><br />
整个结构如图所示</p>
<p ></p>
<p > 系统将要存储的数据最多可分为16中大小,然后分别创建数据空间。避免一条数据被拆分到多个数据块中的复杂度。我们一共预设了13组slab结构,预设的数据大小和预分配的条目为:</p>
<p ></p>
<p > 因此secache要求数据空间最小为10M。当超过这个值时,secache会根据存放数据的频率动态增加各个slab的数据块数量,直到增长到配置好的最大数据量为止。当增长到极限时,各slab的数据块分布将不再变动。如果想重建结构,需要删除缓存文件,重新生成。当无法申请到新的空间之后,将采用lru的策略删除相对不活跃的缓存条目,为新的缓存请求腾出数据空间。</p>
<p > 每个slab结构占用24个字节,组成为:</p>
<p ></p>
<p > 再看一下hash索引表的结构。所有进入secache的数据,key的前4位必须是16进制数据,即0000</p>
<p >-ffff, 共65536种前缀, 每个前缀的索引占用4字节的入口, 所以索引入口区占用空间为65536*4=256k空间。<span class="Apple-converted-space"></span><br />
可以看到,secache的地址数据都是4字节,即最大支持256^4=4G的寻址空间,但是由于PHP在32位系统下的大数上限约为二十亿。所以保险起见,我们强制secache最大仅支持1G空间。</p>
<p > 数据区的数据有两种,一种是实际数据,一种是索引节点数据。实际数据空间占用情况依照slab不同而不同,索引节点的长度是定长:56Bytes。</p>
<p >索引节点结构:</p>