我正在尝试基于分数的PHP内存缓存,但我对性能(如何计数分数和删除低分数记录)有问题。
目标
我有大约一千万张唱片。我只想在内存中缓存最频繁的记录的0.1%,而不是在磁盘上。
我想设置10,000个缓存插槽(0.1%),我只想保持在这些插槽中最频繁的。
尝试/问题
我尝试了基于文件的缓存,它非常慢。
我尝试了MySQL和PostgreSQL,但是由于计算分数和删除低分数记录,它的性能成本过高。
我试过基于时间的缓存,例如。xcache,但是由于我的项目中有太多的数据,所以写的太多了。此外,删除最低分记录和列出所有缓存槽也有问题,因为它是"key->value“。
我找到了Redis,但似乎没有任何分数或类似的东西。
我的问题:
基于分数的缓存应该使用什么缓存方法?
请注意,所有这些帖子都是相似的,但不包含任何可用的答案:
Fastest PHP memory cache/hashtable
In-memory cache with LRU expiration
发布于 2015-07-31 10:40:31
听起来,LRU缓存应该能满足您的需要。您可以像配置LRU缓存一样配置Redis。也许它能很好地处理你的情况。以下是redis docs的一些参考资料:http://redis.io/topics/lru-cache
要快速总结一下,您可以使用“allkeys”驱逐策略,并将"maxmemory“设置为您想要的东西。一旦达到内存限制,redis将释放最近使用最少的项,并将内存使用情况保持在"maxmemory“之下。
另一种选择是使用"memcached",它是内存中的键值存储,默认情况下被配置为LRU缓存。
如果您真的想自己跟踪分数,并且已经有了某种类型的项目评分机制,您可以使用Redis,您可以将SortedSet和Hash放在一起来对缓存项进行排序。
散列将保持缓存的数据,而SortedSet将保持项的排序。
您需要这些SortedSet命令:
每次插入后,您必须手动检查SortedSet的计数,并限制缓存中的项目数。总的来说,算法应该是这样的:
缓存插入:
HSET "cacheKey" "itemName" "itemValue"
ZADD "rankingKey" "itemScore" "itemName"
count = ZCARD "rankingKey"
if (count > limit)
lowestRankedItem = ZRANGE "rankingKey" 0 0
ZREM "rankingKey" lowestRankedItem
HDEL "cacheKey" lowestRankedItem查找将是:
itemValue = HGET "cacheKey" "itemName"发布于 2015-07-31 14:59:51
纯LRU并不是很好,因为它缓存了所有的新键,我只需要缓存0.1%的数据(高分),所以不会有太多无用的写入。
当然,我将按照下一个版本的建议实现Redis方法,因为应该更快。所以,只有当你没有红宝石的时候才使用这个,如果你不能决定任何其他的得分,只需要计算每一段时间的点击数,或者只是想保持简单。
但我目前最好的尝试是使用key=>value memcached,只是现在进行测试,而且看起来既快速又稳定。在我以错误的方式思考之前。
当需要缓存新项时,我们检查缓存中是否存在得分(cache用于键包含int),如果是且小于我们的限制,则增加分数,如果是和高于限制,则获取内容并保存到缓存中。如果缓存中包含的不是数字,那就是我们的内容(高分)。如果key的缓存根本不存在,我们将int 1作为得分保存到非常短的TTL缓存中,并且我们只是获得内容而没有任何缓存(低分数)。
<?php
$minhits = 10; // Min 10 hits for one key
$minhitstime = 60 // Max 60 seconds between hits
$cachettl = 3600; // Cache for 3600 seconds
$key = "article1";
$mem = new Memcached();
$mem->addServer('localhost', 11211);
$content = $mem->get($key);
if(!$content OR (is_int($content) AND $content<$minhits)){
$content = getArticleContent(); // Your own function
}
if(is_int($c)){
if($c>=$minhits){
$mem->set($key, $content, $cachettl);
} else {
$mem->set($key, ($c+1), $minhitstime);
}
} elseif($c) {
$content = $c;
} else {
$mem->set($key, 1, $minhitstime);
}
echo $content;
?>此外,请不要尝试缓存纯int值;)如果是,您必须编辑代码。
https://stackoverflow.com/questions/31729359
复制相似问题