最近笔者自己的项目中,遇到了乐观锁的需求。但是redis没有这个操作,无奈,看了memcache天然的支持这种并发原语,即:GETS和CAS操作。因此准备打算继续使用REDIS,业务没有那么强的时序执行要求,因此可以使用没有CAS的算法在某种程度上解决。
我们为什么要使用这种并发原语呢?如果是单机版的,我们可以通过通过加锁同步就可以解决执行时序的问题。但是我们的应用是分布式的,无状态的应用服务器通过负载均衡,部署到了多台。加锁也解决不了多台服务器的时序执行。
如果不采用CAS,则有如下的情景:
第一步,A取出数据对象X;
第二步,B取出数据对象X;
第三步,B修改数据对象X,并将其放入缓存;
第四步,A修改数据对象X,并将其放入缓存。
我们可以发现,第四步中会产生数据写入冲突。
如果采用CAS协议,则是如下的情景。
第一步,A取出数据对象X,并获取到CAS-ID1;
第二步,B取出数据对象X,并获取到CAS-ID2;
第三步,B修改数据对象X,在写入缓存前,检查CAS-ID与缓存空间中该数据的CAS-ID是否一致。结果是“一致”,就将修改后的带有CAS-ID2的X写入到缓存。
第四步,A修改数据对象Y,在写入缓存前,检查CAS-ID与缓存空间中该数据的CAS-ID是否一致。结果是“不一致”,则拒绝写入,返回存储失败。
我们可以通过重试,或者其他业务逻辑解决第四步设置失败的问题。
没有CAS的方案
一般使用redis用这个算法,可以从某种程度上保证时序性。
SETNX key value
将key 的值设为value ,当且仅当key 不存在。
返回值:
设置成功,返回1。
设置失败,返回0。
if (memcache.get(key) == null) {
// 3 min timeout to avoid mutex holder crash
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();
}
}
最初的解决方案:
利用memcached的add操作的原子性来控制并发,具体方式如下:
1.申请锁:在校验是否创建过活动前,执行add操作key为key,如果add操作失败,则表示有另外的进程在并发的为该key创建活动,返回创建失败。否则表示无并发
2.执行创建活动
3.释放锁:创建活动完成后,执行delete操作,删除该key。
问题:
1.memcached中存放的值有有效期,即过期后自动失效,如add过M1后,M1失效,可以在此add成功
2.即使通过配置,可以使memcached永久有效,即不设有效期,memcached有容量限制,当容量不够后会进行自动替换,即有可能add过M1后,M1被其他key值置换掉,则再次add可以成功。
3.此外,memcached是基于内存的,掉电后数据会全部丢失,导致重启后所有memberId均可重新add。
解决方案
针对上述的几个问题,根本原因是add操作有时效性,过期,被替换,重启,都会是原来的add操作失效。解决该问题有方法
1.减轻时效性的影响,使用memcached CAS(check and set)方式。
使用CAS的方案
CAS的基本原理
基本原理非常简单,一言以蔽之,就是“版本号”。每个存储的数据对象,多有一个版本号。我们可以从下面的例子来理解:
final GetsResponse<Object> response = memcachedClient.gets("key");
boolean flag = memcachedClient.cas("key", new CASOperation<Object>() {
@Override
public int getMaxTries() {
//重试次数
return 1;
}
@Override
public Object getNewValue(long currentCAS,
Object currentValue) {
oldCAS = response.getCas();
if (checkCAS()) {//比较CAS值
value = db.get(key);
return value;
}else{
//抛出异常,或者其他业务逻辑
}
}
});
}
分享到:
相关推荐
10. 关键词:并发服务器、高并发WEB服务器设计、Nginx、Memcached、分布式缓存、一致性哈希算法、云计算。 整体而言,文章所探讨的技术内容和知识点涉及了现代高性能WEB服务器设计的关键技术和策略,以及它们在实际...
这两个扩展提供了与Memcached服务器交互的API,可以进行存储、获取、删除等操作。`Memcached`扩展相比于`Memcache`在功能上有所增强,支持更多高级特性,如SASL认证、一致性哈希等。 2. Memcached缓存原理: ...
3. **锁和并发控制**:由于在内核环境中,多线程和中断处理是常见的,因此内核态memcached必须考虑并发访问的同步问题,可能使用自旋锁、读写锁等同步原语来保证数据一致性。 4. **网络协议栈集成**:内核态的...
此外,还支持多键操作如`gets`(获取键的同时校验CAS值,用于防止并发问题)。 **4. 分布式存储与一致性哈希** Memcached的分布式特性源于客户端的分发策略,其中最常见的是一致性哈希算法。该算法通过计算哈希值...
cas-client-support-distributed-memcached-3.2.0.jar
#### 一、Memcached概述与背景 Memcached是一个高效、开源、分布式的内存对象缓存系统,旨在通过减轻数据库负担,加速动态Web应用程序的响应速度。它通过在内存中存储键值对的形式缓存数据,减少数据库的查询次数,...
<bean id="ticketRegistry" class="org.jasig.cas.ticket.registry.MemCacheTicketRegistry"> <constructor-arg index="0"> <bean class="net.spy.memcached.spring.MemcachedClientFactoryBean" p:servers=...
标题"memcached 64位 window"指的是在Windows操作系统上运行的64位版本的Memcached缓存系统。Memcached是一种分布式内存对象缓存系统,广泛用于减轻数据库负载,提高Web应用的性能。由于是64位版本,这意味着它可以...
本资料包包含“Memcached实例与文档”,是学习和理解Memcached工作原理及应用的重要资源。 一、Memcached的基本概念 Memcached基于键值对(key-value)存储,提供简单的文本协议,易于与其他编程语言集成。它的设计...
php操作memcached类 简单实用
- **4.2.3 线程安全**:Memcached在处理并发访问时会确保线程安全,避免同时对同一个Chunk进行操作。 - **4.2.4 LRU**:为了管理内存资源,Memcached采用了LRU算法。当内存紧张时,会优先释放最近最少使用的数据。...
这些库提供了与Memcached服务器交互的API,使得开发者能够在.NET环境中轻松地集成Memcached服务。下面我们将详细介绍使用C#实现Memcached的步骤: 1. **安装库**:首先,你需要通过NuGet包管理器在你的C#项目中安装...
而PHP实现的Memcached队列类则是在这一基础上进行的扩展,它允许开发者创建并管理一个基于Memcached的队列,以支持并发操作和特定的队列策略。 首先,这个类提供了多进程并发写入和读取的能力。这意味着多个PHP进程...
**Memcached 安装与使用详解** Memcached 是一款高性能的分布式内存缓存系统,用于在Web应用中减轻数据库负载。它将数据存储在内存中,以键值对的形式提供快速访问,尤其适用于高并发场景。Memcached 使用简单,可...
通过`memcached-client.php`这样的客户端脚本,我们可以轻松地实现与Memcached服务器的通信,利用其高效缓存机制来优化数据库操作。同时,配合`学习文档Url.txt`中的指南,开发者可以更深入地理解和掌握Memcached在...
这些库提供了方便的方法来操作Memcached服务器,包括设置、获取、删除和过期等操作。 3. **源码结构分析** 解压后的"memcached工具类源码"可能包含以下部分: - **Memcached客户端连接器**:初始化和管理到...
4. 兼容性改进:可能改善了与不同操作系统或库(如libevent)的兼容性,使得 Memcached 能在更广泛的环境中稳定运行。 其中,libevent-2.0.11-stable.a 是一个事件库,用于处理网络连接和I/O事件。在 Memcached 中...
在Java应用中集成memcached,可以显著提升数据读取速度,尤其适用于高并发、读多写少的场景。但同时也要注意,memcached并非万能解决方案,对于需要持久化存储和复杂查询的数据,仍需依赖数据库。
标签“memcached 服务器端 下载”明确了这是关于获取memcached服务端的资源,而且是下载操作,通常这包括了memcached服务器的运行文件和可能需要的客户端驱动(如PHP扩展)。 在压缩包中的`php_memcached.dll`和`...