[转]Memcache mutex设计模式
场景
Mutex主要用于有大量并发访问并存在cache过期的场合,如
- 首页top 10, 由数据库加载到memcache缓存n分钟
- 微博中名人的content cache, 一旦不存在会大量请求不能命中并加载数据库
- 需要执行多个IO操作生成的数据存在cache中, 比如查询db多次
问题
在大并发的场合,当cache失效时,大量并发同时取不到cache,会同一瞬间去访问db并回设cache,可能会给系统带来潜在的超负荷风险。我 们曾经在线上系统出现过类似故障。
解决方法
方法一
在load db之前先add一个mutex key, mutex key add成功之后再去做加载db, 如果add失败则sleep之后重试读取原cache数据。为了防止死锁,mutex key也需要设置过期时间。伪代码如下
(注:下文伪代码仅供了解思路,可能存在bug,欢迎随时指出。)
if (memcache.get(key) == null) { // 3 分钟到期以避免 mutex holder crash if (memcache.add(key_mutex, 3 * 60 * 1000) == true) { //在delete之前,当前key_mutex add只能第一次返回true value = db.get(key); memcache.set(key, value); memcache.delete(key_mutex); } else { sleep(50); retry();//sleep之后重试读取原cache数据 }}
方法二
在value内部设置1个超时值(timeout1), timeout1比实际的memcache timeout(timeout2)小。当从cache读取到timeout1发现它已经过期时候,马上延长timeout1并重新设置到cache。然 后再从数据库加载数据并设置到cache中。伪代码如下
v = memcache.get(key);if (v == null) { if (memcache.add(key_mutex, 3 * 60 * 1000) == true) { value = db.get(key); memcache.set(key, value); memcache.delete(key_mutex); } else { sleep(50); retry(); }} else { if (v.timeout <= now()) {//有值但已过期 if (memcache.add(key_mutex, 3 * 60 * 1000) == true) { // extend the timeout for other threads v.timeout += 3 * 60 * 1000; memcache.set(key, v, KEY_TIMEOUT * 2);//这只是为了让它先暂时有效(后面即将更新该过期数据),这样做主要防止
// load the latest value from db
v = db.get(key);
v.timeout = KEY_TIMEOUT;
memcache.set(key, value, KEY_TIMEOUT * 2);
memcache.delete(key_mutex);
} else {
sleep(50);
retry();
}
}
}
相对于方案一
优点:避免cache失效时刻大量请求获取不到mutex并进行sleep
缺点:代码复杂性增大,因此一般场合用方案一也已经足够。
方案二在Memcached FAQ中也有详细介绍 How to prevent clobbering updates, stampeding requests,并且Brad还介绍了用他另外一个 得意的工具 Gearman 来实现单实例设置cache的方法,见 Cache miss stampedes,不过用Gearman来解决就感觉就有点奇技淫巧了。
附:本次Web2.0技术沙龙演讲主题:微博Cache设计谈,需下载请点击演讲稿下menu/download (需登录slideshare)。
转载于:https://www.cnblogs.com/daizhj/articles/1959704.html
[转]Memcache mutex设计模式相关推荐
- Memcache mutex设计模式
2019独角兽企业重金招聘Python工程师标准>>> 周六的S2 Web 2.0技术沙龙上介绍了memcache中使用mutex场景(文后要演讲稿),有网友对详情感兴趣,简单介绍如 ...
- Web开发基本准则-55实录-缓存策略(转)
原文地址:http://www.cnblogs.com/zhengyun_ustc/p/rule2.html 续上篇<Web开发基本准则-55实录-Web访问安全>. Web开发基本准则- ...
- 2010-12-8 学习总结
IDU(埃迪优)世界设计联盟联合业务中心 http://www.jbcidu.com/index 几种特殊的类型设计 http://www.cnblogs.com/Ivony/archive/2009 ...
- 应届生应聘java需要掌握的技能
一般要求 java基础.spring全家桶.分布式.服务器.中间件.数据库oracle. 框架:spring.springMVC.mybatis.springBoot.SpringData. 消息中间 ...
- 设计模式之PHP项目应用——单例模式设计Memcache和Redis操作类
1 单例模式简单介绍 单例模式是一种经常使用的软件设计模式. 在它的核心结构中仅仅包括一个被称为单例类的特殊类. 通过单例模式能够保证系统中一个类仅仅有一个实例并且该实例易于外界訪问.从而方便对实例个 ...
- php设计是什么意思,php的设计模式是什么
设计模式 单例模式解决的是如何在整个项目中创建唯一对象实例的问题,工厂模式解决的是如何不通过new建立实例对象的方法.(php视频教程) 单例模式$_instance必须声明为静态的私有变量 构造函数 ...
- 浅谈Laravel中的设计模式(四) Contract 契约模式
阅读时长:3分钟 技术预备:熟悉Laravel的使用 契约模式(Contract) 一.首先什么是契约模式呢? 学过Java的童鞋一定知道interface.抽象类之类的概念. 主要就是为了具有相同操 ...
- 大话PHP设计模式:类自动载入、PSR-0规范、链式操作、11种面向对象设计模式实现和使用、OOP的基本原则和自动加载配置...
一.类自动载入 SPL函数 (standard php librarys) 类自动载入,尽管 __autoload() 函数也能自动加载类和接口,但更建议使用 spl_autoload_registe ...
- 互联网高并发架构设计模式
2019独角兽企业重金招聘Python工程师标准>>> 前言 随着互联网的快速发展,很多传统行业都开始将原有的产品互联网化移动化,这其中就涉及到对原有系统的改造,因为之前大部分时间都 ...
最新文章
- elasticsearch 客户端工具_elasticsearch初使用
- python怎么使用训练好的模型设计_tensorflow训练好的模型怎么调用?
- encountered end of file_需要给自己一个end
- FPGA进阶篇--SPI控制双通道16bit串行DAC8532
- bzoj 4012: [HNOI2015]开店 主席树
- HP P2000 RAID-5两块盘离线的数据恢复报告
- #时间预测算法_【时间序列】时序预测竞赛之异常检测算法综述
- Django Rest Framework(一)
- 如何解决linux标准输出中带颜色的字符
- [转]如何编程实现 2 + 2 = 5?
- Java猜拳小游戏(剪刀、石头、布)
- linux安装vmware没有网络,关于无桌面的linux安装VMWare Tools配置的教程
- 车牌识别存储云服务器,云端(服务器)车牌识别技术
- 何为线性时不变系统!详解
- 关于企业数字化转型的建议
- 今晚7:30 | 连界、将门、百度、碧桂园创投四位大佬眼中的AI世界,是继续高深还是回归商业本质?...
- 在OpenGL中实现Geometry Instancing
- nginx日志格式及自定义日志配置
- Delphi测试ODBC连接达梦数据库
- 计算机屏幕分辨率在哪看,笔记本屏幕分辨率有几种 怎么看电脑分辨率
热门文章
- 十六进制转换成字符串——CRC
- hbase 命令_HBase原理与实践 | 生产环境上线前真的优化过吗?
- 【kafka】Kafka 之 Group 状态变化分析及 Rebalance 过程
- 【kafka】kafka log 存储时间 小于 offset 存储时间 offset存在但是消费不到
- 【Flink】Flink Heartbeat of TaskManager with id timed out.
- 40-400-044-运维-优化-MySQL order by 优化
- 【Es】Elasticsearch 7.x 新的集群协调层
- 【Linux】Linux 生成证书 keytool 命令找不到
- 77-spark与storm比对与选型
- Spring : ConfigurableBeanFactory 配置能力