Memcached的LRU算法
题外话
最近计划对Memcached做一些尝试性的改造,主要是针对Memcached在处理过期数据的时候进行改造,以实现在一个缓存的过期时间达到的时候,可以对该缓存的数据进行一个验证和存储的处理。
这个需求,主要是为了解决MySQL的写入瓶颈,通过延期、合并写入请求来减少MySQL的并发写入量。现在逐渐记录出来和有需要的朋友一起讨论。当然,今天的主要内容是关于LRU的部分。
LRU算法
LRU是Least Recently Used最近最少使用算法。源于操作系统使用的一种算法,对于在内存中但最近又不用的数据块叫做LRU,操作系统会将那些属于LRU的数据移出内存,从而腾出空间来加载另外的数据。
我们来看Memcached(版本 1.4.9)的相关代码:
/* expires items that are more recent than the oldest_live setting. */ |
void do_item_flush_expired(void) { |
int i; |
item *iter, *next; |
if (settings.oldest_live == 0) |
return; |
for (i = 0; i < LARGEST_ID; i++) { |
/* The LRU is sorted in decreasing time order, and an item's timestamp |
* is never newer than its last access time, so we only need to walk |
* back until we hit an item older than the oldest_live time. |
* The oldest_live checking will auto-expire the remaining items. |
*/ |
for (iter = heads[i]; iter != NULL; iter = next) { |
if (iter->time >= settings.oldest_live) { |
next = iter->next; |
if ((iter->it_flags & ITEM_SLABBED) == 0) { |
do_item_unlink(iter); |
} |
} else { |
/* We've hit the first old item. Continue to the next queue. */ |
break; |
} |
} |
} |
} |
属于LRU的item是被时间逆序排序了,一个item的失效时间应该是永远比它自身上次被访问的时间大。所以在找到一个item的失效时间比oldest_live这个时间小之前,我们只需要把已经逆序排序的item继续往结尾遍历即可,一旦找到这个item,其他剩余的item也就可以判定为过期了。
如何改动?
我们的思路是让Memcached来作为MySQL的中间承接方,其实LRU算法并不是最适合。列举两种方案:
- 继续采用LRU算法,我们需要对Memcached进行改造的是do_item_flush_expired这个函数的执行频度,同时改造do_item_unlink函数来适应需求。
- 改用FIFO(先入先出)算法,彻底放弃Memcachd的整个过期处理机制或者另外添加一个FIFO算法序列,来专门为我们的业务需要服务。
为什么写这篇文章?
想写出来和大家一起讨论,看有没有其他的一些更好的用来解决MySQL写入并发的方案。
Tags: MySQL效率, 算法
版权声明:原创作品,欢迎转载,转载时请务必以超链接形式标明文章原始地址、作者信息和本声明。
已有 15 条评论 »
- ElmerZhang2011-10-26 at 16:12:07
你的意思是要改造Memcache,当其中某个数据过期被删除前,先将它存入Mysql?
这样不太好吧。Memcache本身就是一个高速缓存,把他和Mysql绑起来,难免会有问题。假如Memcache满了,然后有大量新数据涌进来,那么Memcache中过期数据往Mysql中转存这一步就有可能会是一个瓶颈,旧数据被清掉的太慢,新数据保存失败。
我觉得还是单独写个脚本定时将MC中的数据转存入Mysql比较好。
另外Memcache也可以考虑换成Redis,Redis可以做执久化和replication,防止进程重启或者突然挂掉导致数据丢失。- kimi2011-10-26 at 16:57:41
怪我没说清楚,比如我们的业务模型就是社交游戏,社交游戏的用户特点,就是上线之后开始游戏,操作时候十分钟之内关闭游戏下线。我们先定义PHP和MySQL之间有个中间件叫Mcache
在这个过程中,比如用户刚上线
SELECT money,exp FROM user WHERE uid = ‘1’; 于是PHP把这个query通过PHP扩展发给了Mcache,Mcache接到这个query,发现没有数据,于是就向MySQL查到数据存下来再返回给PHP;
几分钟之后,又来了一个操作,加了4个金币UPDATE user SET money=money+4 WHERE uid = ‘1’; 这时候,Mcache接到这个query,发现已经有数据了,就直接在Mcache中对这个数据修改;
几分钟之后,又来了一个操作,加了10个金币 5点经验UPDATE user SET money=money+4, exp=exp+5 WHERE uid = ‘1’; 这时候,Mcache接到这个query,发现已经有数据了,就直接在Mcache中对这个数据修改;
又来了一个操作,请求用户当前的金币和经验SELECT money,exp FROM user WHERE uid = ‘1’; 这时候,Mcache直接就把最新的query发给PHP去了。
当30分钟之后,Mcache自动将这条记录update给MySQL。
这样能减少对MySQL的写入并发,之所以不用NOSQL的方案,是目前NOSQL的方案无法解决回档的问题。而MySQL在热备、增量备份方面的优势是NOSQL方案无法比拟的。你说呢?
- ElmerZhang2011-10-26 at 17:34:40
明白了。那么将数据读到缓存,更新缓存,将缓存数据持久化到Mysql,都应该是Mcache这个中间件做的事情,而不是Memcached做的,所以只要把这个中间件做好就OK了呀。
我提到Redis的意思是让它替代Memcache做缓存,而不是做持久化存储。
关键数据确实仍然应该用Mysql存储,NoSQL在数据备份、恢复等方面比Mysql还差点。- kimi2011-10-26 at 19:15:33
确实,关键性的数据还是得用MySQL存储。为了避免制造重复车轮,计划是在Memcached代码上去做Mcache这个东西。然后开源发出来。有木有兴趣的说~
回复
回复 - kaka2011-10-26 at 23:18:36
思路确实不错,“写”也可以放内存中执行了。。。
不过如何应对灾难情况呢?比如:
“当30分钟之后,Mcache自动将这条记录update给MySQL” ---
这半小时内,会用内存来存一些金币或经验的操作数据,如果出现了XXX问题造成了机器重启,内存数据丢失又如何应对呢?
- kimi2011-10-27 at 09:35:25
在这种情况下每个用户会最多丢失半个小时的数据。任何不在计划内的机器重启对MySQL都有可能造成致命性的损害。当然这种不在计划内的机器重启对Mcache也会造成致命性的损害(丢失半个小时的数据)。
- kaka2011-10-27 at 18:23:42
任何不在计划内的机器重启是可能会造成致命伤害,不过如果是从怎样把这种伤害降到最小的角度来讨论呢??
比如,若用redis是不是出现XXX情况会好一些?
redis也是基于内存存储的,不过同时具有以下特点:
1、redis具有持久化机制,可以定期将内存中的数据持久化到硬盘上。
2、redis具备binlog功能,可以将所有操作写入日志,当redis出现故障,可依照binlog进行数据恢复。
- kimi2011-10-27 at 18:41:09
说的有道理,主要是我之前读过Memcached的代码,所以就直接想到用Memcached了。利用Memcached处理过期数据的时候将数据写入MySQL中去。
我来研究下Redis的代码,看什么时候做这个写入MySQL的操作比较合适。
- kaka2011-10-27 at 22:49:30
redis这2年很火的,sina微博就是用的redis。。
不过我的项目没达到那个量级,所以只是看过一些资料,没有实践经验。。希望以后可以看到kimi兄的分享哦~~~ :)
- kimi2011-10-28 at 16:22:00
之前公司有研究过redis,主要是当时redis需要内存完全大于数据,否则会有性能问题,持久化的特点数据亦不会自动过期,所以就没过多关注,在这点上,Membase就完全超过redis。
- kaka2011-10-30 at 00:14:38
Membase 能搜到的资料还是比较少的,在你的一篇blog上看到过介绍,貌似优点很多。。。
想请教下kimi兄在生产环境实践中,有无遇到什么问题或者瓶颈??如果现在一个项目想选择nosql的缓存方案,
是否是首推Membase??
- kimi2011-10-30 at 18:17:06
看数据量吧,目前是各有优缺点,我们是在生产环境采用的Membase,放弃Tokyotyrant、Redis也是有原因的,推荐采用Membase,但是Membase的资料却是太少了。
- tcl2011-11-20 at 01:19:25
1.个人觉得哪有完美的方案,没有。都是看实际需求,可以不可以满足。出现错误情况能不能忍受,能忍受到什么程度的错误
2.当时做游戏的时候也是将数据写到memcached,然后后台有个程序定时的从memcached中取数据,写到mysql,往memcached中的写数据的时候设置永不过期,后台程序取走数据,写到mysql的时候再设置memcached中数据过期。但是数据都放到了memcached中了。万一memcached挂了,就歇菜了。这块是不是写的时候写到两个memcached中,还是说写到一个memcached集群里面。
回复
回复
回复
回复
回复 - sogo2012-01-30 at 11:55:10
cache 除了解决高并发方面的问题,想请教一下,读cache 与读取mysql 的时间上面,那个更快,如果评测?
回复 - freeacger2012-03-30 at 19:17:12
博主.你的代码插件用的是啥,能否告知?
Memcached的LRU算法相关推荐
- Redis的LRU算法
2019独角兽企业重金招聘Python工程师标准>>> 整理自官方文档:将redis当做使用LRU算法的缓存来使用 当Redis被当做缓存来使用,当你新增数据时,让它自动地回收旧数据 ...
- 将redis当做使用LRU算法的缓存来使用
当Redis被当做缓存来使用,当你新增数据时,让它自动地回收旧数据是件很方便的事情.这个行为在开发者社区非常有名,因为它是流行的memcached系统的默认行为. LRU是Redis唯一支持的回收方法 ...
- Memcached的LRU策略
前言 从 Memcached1.5 开始,实现了一个改良的 LRU 算法,也叫做分段 LRU(Segmented LRU)算法,新算法主要是为了更好的利用内存,并提升性能.包含了二个重要的线程:mai ...
- LRU算法 -- 链表 完整实现
LRU算法(Least Recently Used) 算是我们经常遇到的一种淘汰算法,其中内存管理模块进行内存页回收时有用到,针对不经常使用的内存页,LRU淘汰策略能够将该内存页回收给操作系统. 属于 ...
- 漫画:什么是LRU算法?
本期封面作者:A17 ----- 两个月前 ----- 用户信息当然是存在数据库里.但是由于我们对用户系统的性能要求比较高,显然不能每一次请求都去查询数据库. 所以,小灰在内存中创建了一个哈希表作 ...
- 【腾讯三面】你能现场写一下LRU算法吗?
" 金三银四,又到了换工作的黄金期.各位小伙伴们都准备好了吗? " 这句话大家是不是最近已经要看吐了呢? 每当这个时候,就证明招聘旺季又来啦~ 春招.校招.社招-- 那你真的准备好 ...
- LRU算法确定最后使用时间的顺序
LRU算法是经常采用的页面置换算法,并被认为是相当好的,但是存在如何实现它的问题.LRU算法需要实际硬件的支持.其问题是怎么确定最后使用时间的顺序,对此有两种可行的办法: 1.计数器. 2.栈.
- java 最少使用(lru)置换算法_「面试」LRU了解么?看看LinkedHashMap如何实现LRU算法...
以下内容均是本人原创,希望你看完之后能有更多更深入的了解,欢迎关注➕ 问题:使用Java完成一个简单的LRU算法 什么是LRU算法 LRU(Least Recently Used),也就是最近最少使用 ...
- Android图片缓存之Lru算法
前言: 上篇我们总结了Bitmap的处理,同时对比了各种处理的效率以及对内存占用大小.我们得知一个应用如果使用大量图片就会导致OOM(out of memory),那该如何处理才能近可能的降低oom发 ...
最新文章
- opencv-python图像处理之让你的照片变旧
- java生成excel_java生成excel并下载功能
- 常见 Serverless 架构模式
- RocketMQ-什么是死信队列?怎么解决
- 进程有一个全局变量 i,还有有两个线程。i++ 在两个线程里边分别执行 100 次,能得到的最大值和最小值分别是多少?
- 牛逼!不得不服,第一次有人把Java 反射机制讲解这么透!
- 【Floyed】【匈牙利算法】导弹(jzoj 1610)
- CleanMyMac for mac之偏好设置
- CASE WHEN语句中加IN应该如何使用
- 最简单爬虫rvest_告别复制粘贴
- 求n!的位数以及求n!具体的值(C or C++)
- Spket,eclipse下安装Spket插件,格式化js
- 【Unity3D】计算二维向量夹角(-180到180)
- Git正解 脱水版 【7. Git命令】
- 机房服务器巡视项目,年底,机房巡检不能少
- 使用安全浏览器将网页保存为pdf的方法步骤
- win10 uwp 相机的分辨率设置方法
- 计算机专业个税,税后工资个税计算器
- mysql过载保护_腾讯后台开发技术总监浅谈过载保护 小心雪崩效应
- 音质好的蓝牙耳机有哪些?音质好的蓝牙耳机推荐
热门文章
- 论文中可以让代码变得非常好看的工具
- C/C++面试题-2 之2/2
- Android “adb”不是内部或外部命令,也不是可运行的程序或批处理文件
- illustrator cs5 for mac 官方简体中文版 破解
- 怎样两个网络互远程连接计算机,两个电脑怎么远程控制两个方法教你
- iOS 自定义导航栏 NavigationBar
- 爬虫抓取某饿了app商铺的评论数据
- 你真的了解getline()的返回值吗?—— basic_istream::getline() 与 string::getline
- 前端、后台、客户端以及服务器
- 高端大气的艺术海报的ps教程