缓存的设计及PHP实现LFU
- 命中率:指请求缓存次数和缓存返回正确结果次数的比例。比例越高,缓存的使用率越高,用来衡量缓存机智的好坏和效率。如果数据频繁更新,命中率就会降低,这个时候需要考虑缓存的合理性。命中率=命中次数/请求次数。
- 缓存更新策略主要有三个:
FIFO先进先出,如果一个数据最先进入缓存中,当缓存满了以后,就应该最早淘汰掉。
LFU最近最少使用,如果一个数据在最近一段时间内使用次数很少,那么在将来一段时间内被使用的可能性也很小。即:当缓存满了以后,应当把最少被访问的数据淘汰。(LFU是淘汰一段时间内使用次数最少的数据。)
LRU最近最久未使用,如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小。即:当缓存满了以后,应当把最久没有被访问到的数据淘汰。(LRU是淘汰最长时间没有被使用的数据。) - 缓存最大数据量是在缓存中能处理元素的最大个数或所能使用的最大存储空间。
- 定义两个关联数组,key都一样,一个数组叫kv数组,存值,形如key=>value,一个数组叫kc数组,存值被访问的次数,形如key=>count。
- 定义请求数requestNum和命中数hitNum,来获得命中率。
- 定义缓存当前数据个数size和缓存总大小totalSize。
- 定义方法包括:get、add、getHitRate、cleanup等。
get:通过传入key,从kv数组中返回其值,同时,kc数组中该key对应的count值+1。
add:通过传入key和value,将数据添加到存值的关联数组中。这时候要考虑LFU,如果缓存没满,直接加进去就行,但如果缓存已经满了,添加新的数据时,最近最少未被使用的数据就要踢掉(cleanup)。
cleanup:当有数据需要更新的时候,先在kv数组中插入一个key=>value,在kc数组中根据value的访问次数count值,找出最少被访问的几个数据,通过它们的key,把kv数组中的值删掉。
getHitRate:计算命中率。每当用户请求(get)数据一次,请求数requestNum就+1,如果请求的值在缓存里面找到了,命中数hitNum就+1,则命中率hitRate=hitNum/totalRequestNum。
<?php
// 设计一个简单的缓存
class strCache {
// 缓存总大小
var $totalSize = 5;
// 访问数
var $requestNum = 0;
// 命中数
var $hitNum = 0; // 存值key=>value
var $arr1 = array();
// 存访问次数key=>count
var $arr2 = array(); public function get($key) {
$result = "";
$this->requestNum += 1;
if ($this->arr1[$key]) {
$this->hitNum += 1;
$count = 1;
if ($this->arr2[$key]) {
$count += $this->arr2[$key];
}
$arr2[$key] = $count;
$result = $this->arr1[$key];
}
return $result;
} public function add($key, $value) {
$this->cleanup();
$this->arr1[$key] = $value;
$this->arr2[$key] += 1;
return true;
} public function cleanup() {
if (count($this->arr1) == $this->totalSize) {
asort($this->arr2);
$keys = array_keys($this->arr2);
$k = $keys[0];
unset($this->arr1[$k]);
unset($this->arr2[$k]);
}
return true;
} public function getHitRate() {
$hitRate = 0;
if ($this->requestNum != 0) {
$hitRate = $this->hitNum / $this->requestNum;
}
return $hitRate;
}
} // 测试
$strObj = new strCache();
$strObj->add('a', 'wuhan');
$strObj->add('b', 'heilongjiang');
$strObj->add('c', 'shanghai');
$strObj->add('d', 'beijing'); print_r($strObj->arr1);
echo "<pre>";
echo $strObj->get('a');
echo "<pre>";
echo $strObj->get('aa');
echo "<pre>";
echo $strObj->hitNum;
echo "<pre>";
echo $strObj->getHitRate();
缓存的设计及PHP实现LFU的更多相关文章
- Redis缓存策略设计及常见问题
Redis缓存设计及常见问题 缓存能够有效地加速应用的读写速度,同时也可以降低后端负载,对日常应用的开发至关重要.下面会介绍缓存使用技巧和设计方案,包含如下内容:缓存的收益和成本分析.缓存更新策略的选 ...
- .NET 缓存模块设计
上一篇谈了我对缓存的概念,框架上的理解和看法,这篇承接上篇讲讲我自己的缓存模块设计实践. 基本的缓存模块设计 最基础的缓存模块一定有一个统一的CacheHelper,如下: public interf ...
- IOS编程 图片缓存模块设计
手机客户端为什么会留存下来?而不是被一味的Wap替代掉?因为手机客户端有Wap无可替代的优势,就是自身较强的计算能力. 手机中不可避免的一环:图片缓存,在软件的整个运行过程中显得尤为重要. 先简单说一 ...
- 利用Java的读写锁实现缓存的设计
Java中的读写锁: 多个读锁不互斥, 读锁与写锁互斥, 写锁与写锁互斥, 这是由JVM自行控制的,我们只要上好相应的锁即可. 缓存的设计: package com.cn.gbx; import ja ...
- atitit。浏览器缓存机制 and 微信浏览器防止缓存的设计 attilax 总结
atitit.浏览器缓存机制 and 微信浏览器防止缓存的设计 attilax 总结 1. 缓存的一些机制 1 1.1. http 304 1 1.2. 浏览器刷新的处理机制 1 1.3. Expir ...
- 《深入理解mybatis原理7》 MyBatis的二级缓存的设计原理
<深入理解mybatis原理> MyBatis的二级缓存的设计原理 MyBatis的二级缓存是Application级别的缓存,它可以提高对数据库查询的效率,以提高应用的性能.本文将全面分 ...
- Redis缓存的设计、性能、应用与数据集群同步
Redis缓存的设计.性能.应用与数据集群同步 http://youzhixueyuan.com/design-performance-and-application-of-redis-cache.h ...
- 简单服务端缓存API设计
Want 我们希望设计一套缓存API,适应不同的缓存产品,并且基于Spring框架完美集成应用开发. 本文旨在针对缓存产品定义一个轻量级的客户端访问框架,目标支持多种缓存产品,面向接口编程,目前支持简 ...
- 《深入理解mybatis原理》 MyBatis的二级缓存的设计原理
MyBatis的二级缓存是Application级别的缓存,它可以提高对数据库查询的效率,以提高应用的性能.本文将全面分析MyBatis的二级缓存的设计原理. 如上图所示,当开一个会话时,一个SqlS ...
随机推荐
- 转载:Databricks孟祥瑞:ALS 在 Spark MLlib 中的实现
Databricks孟祥瑞:ALS 在 Spark MLlib 中的实现 发表于2015-05-07 21:58| 10255次阅读| 来源<程序员>电子刊| 9 条评论| 作者孟祥瑞 大 ...
- JavaScript中class类的介绍
class的概念 一.我们为什么要用到class类? 因为通过class类来创建对象,使得开发者不必写重复的代码,以达到代码复用的目的.它基于的逻辑是,两个或多个对象的结构功能类似,可以抽象出一个模板 ...
- OpenFOAM——绕流振动
流体的物性参数为: 密度:1kg/m3 粘度系数:0.01N·s/m2 首先进行建模操作,任何建模软件均可,本算例在ICEM建模和进行网格划分,生成的网格如下: 接下来转入Open ...
- Hadoop运行原理总结(详细)
本编随笔是小编个人参照个人的笔记.官方文档以及网上的资料等后对HDFS的概念以及运行原理进行系统性地归纳,说起来真的惭愧呀,自学了很长一段时间也没有对Hadoop知识点进行归纳,有时候在实战中或者与别 ...
- golang rabbitmq 的学习
https://www.rabbitmq.com/tutorials/tutorial-one-go.html Rabbitmq的任务分发机制 producer_task.go package mai ...
- SymPy解方程的实现
https://www.cnblogs.com/zgyc/p/6277562.html SymPy完全是用Python写的,并不需要外部的库 原理: 单纯用语言内置的运算与变量解决的是,由值求结果.如 ...
- Android: VIVO手机setSpeakerphoneOn p无效,无法切换speaker的问题
setSpeakerphoneOn 方法可以使语音和通话能够强制从手机的扬声器输出,不过在测试了众多手机在调用了这个API之后都可以,唯独有一款VIVO手机不可以: .小米6X(9.0) .Samsu ...
- ARM USB 通信(转)
ARM USB 通信 采用ZLG的动态链接库,动态装载. ARM是Context-M3-1343. 在C++ Builder 6 中开发的上位机通信软件. USB通信代码如下: //--------- ...
- Mysql 插入自增的最大版本号
有一个需求,在历史表中,一条数据,在最大版本号上进行自增 INSERT Biz_CourseStudyHistory ( contentStudyID, courseWareID, versionNO ...
- kafka集群部署以及单机部署
kafka单机部署 一.环境准备 当前环境:centos7.3一台软件版本:kafka_2.12部署目录:/usr/local/kafka启动端口:9092配置文件:/usr/local/kafk ...