使用memcached进行并发控制(写的非常好)
来源:互联网 发布:威力导演 知乎 编辑:程序博客网 时间:2024/05/16 11:15
原文:http://jiangbo.me/blog/2011/02/27/post/
使用memcached进行并发控制
引子
一个使用缓存进行并发控制的讨论,让我学习到成本与收益间的平衡,以及何为真正的可用性......
防止并发有多种方式,本文只涉及使用缓存memcached控制。
并发场景:
用例:SNS系统中具有高级会员资格的人发起活动。
业务规则:1.一个人同时只能创建一个活动。2.具有高级会员资格。
基本流程如下:
这个流程中存在明显的并发问题,当进程A校验过会员M有资格,并且为创建过活动,但为开始执行创建操作,此时另一个进程B也进行了规则判断,顺利通过,并完成创建操作,此时A继续执行,则会产生两条M的活动。(这个并发场景很简单,很普遍)
最初的解决方案:
计划利用memcached的add操作的原子性来控制并发,具体方式如下:
1.申请锁:在校验是否创建过活动前,执行add操作key为memberId,如果add操作失败,则表示有另外的进程在并发的为该memberId创建活动,返回创建失败。否则表示无并发
2.执行创建活动
3.释放锁:创建活动完成后,执行delete操作,删除该memberId。
问题:
如此实现存在一些问题:
1.memcached中存放的值有有效期,即过期后自动失效,如add过M1后,M1失效,可以在此add成功
2.即使通过配置,可以使memcached永久有效,即不设有效期,memcached有容量限制,当容量不够后会进行自动替换,即有可能add过M1后,M1被其他key值置换掉,则再次add可以成功。
3.此外,memcached是基于内存的,掉电后数据会全部丢失,导致重启后所有memberId均可重新add。
应对问题:
针对上述的几个问题,根本原因是add操作有时效性,过期,被替换,重启,都会是原来的add操作失效。解决该问题有两个方法:
1.采用持久化的缓存解决方法,如TT(Tokyo Tyrant:http://fallabs.com/tokyotyrant/)
2.减轻时效性的影响,使用memcached CAS(check and set)方式。
第一种不必解释了,很简单,原来的所有问题都是时效性惹得祸,时效性源于memcached是基于内存的,那么采用持久话存储的TT可以彻底根治这个问题。
第二种方式需要简单介绍下:
memcached中除了add操作是原子的,还有另外两个操作也是原子的:incr和decr,使用CAS模式即:
1.预先在memcached中设置一个key值,假设为CREATKEY=1
2.每次创建活动时,在规则校验前先get出CREATEKEY=x;
3.进行规则校验
4.执行incr CREATEKEY操作,检验返回值是否为所期望的x+1,如果不是,则说明在此期间有另外的进程执行了incr操作,即存在并发,放弃更新。否则
5.执行创建活动
对比这两种方法,从效果上看可以发现第一种时100%可靠的,不存在问题;第二种,可能存在误判,即本来不存在并发,却被判为并发,如缓存重启,或key值失效后,incr值可能不同于期望值,导致误判。
但是从成本上考虑,TT是持久化的缓存解决方案,完美意味着高成本,我们必须维护持久化数据,而使用memcached的CAS方式,可以以几乎0成本的方式解决时效性问题,尽管存在一点小缺陷,但这种缺陷可以通过简单的重试即可解决。考虑实际的产出比,采用memcached的CAS方式更适合实际情况。
成本与收益间的平衡,做科学与做工程的区别~
- 使用memcached进行并发控制(写的非常好)
- 使用memcached进行并发控制
- SQL优化-索引(写的非常好!)
- Memcached 并发控制 CAS 协议
- 浅析MySQL中exists与in的使用 (写的非常好)
- 浅析MySQL中exists与in的使用 (写的非常好)
- 浅析MySQL中exists与in的使用 (写的非常好)
- 浅析MySQL中exists与in的使用 (写的非常好)
- 初学者使用storyboard(转载,觉得写的非常好)
- 写的非常好的博客
- RxJava的入门(转载的!!写的非常好!)
- 使用Apache对网站的并发请求进行控制,防止网站瘫痪
- linux下的c线程(写的非常好)
- 堆和栈的区别(写的非常好)
- memcached的并发问题
- arm移植过程(写的非常好,受益匪浅)(转发)
- Class.forName详解(写的非常好 学习了!)
- Linux内核启动流程分析(二) 写的非常好
- JAVA迅速解决图片变红、变黑、压缩平滑问题
- 使用opencv开发视频播放器一
- JS处理json格式数据
- 用列转行改写多次关联
- 关于View的getHeight()值为0
- 使用memcached进行并发控制(写的非常好)
- 敏捷软件开发中的配置管理
- Java访问https接口实现
- LeetCode之Sort Colors
- common-pool连接池GenericObjectPool源代码
- 算法导论系列文章之插入排序和归并排序
- Javascript/Node.js 中的 this
- Java安全通信:HTTPS与SSL
- 工作便条ZHAOCM