`

(转)以memcached为例理解乐观锁与悲观锁

阅读更多
(转)以memcached为例理解乐观锁与悲观锁


我们知道,最常用的处理多用户并发访问的方法是加锁。当一个用户锁住数据库中的某个对象时,其他用户就不能再访问该对象。加锁对并发访问的影响体现在锁的粒度上。比如,放在一个表上的锁限制对整个表的并发访问;放在数据页上的锁限制了对整个数据页的访问;放在行上的锁只限制对该行的并发访问。可见行锁粒度最小,并发访问最好,页锁粒度最大,表锁介于2者之间。锁有两种:悲观锁和乐观锁。
这个问题的来源是锁所保护的数据粒度较大数量较多,出现只有部分被保护的数据被修改的情况,则乐观锁通过判断具体关心的数据是否发生变化来决定是回滚操作,可以提高并发度。
在读修改写的访问模式中,加锁的时机有两种选择:读之前或者写之前。
悲观锁假定其他用户企图访问或者改变你正在访问、更改的对象的概率是很高的,因此在悲观锁的环境中,在你开始改变此对象之前就将该对象锁住,并且直到你提交了所作的更改之后才释放锁。悲观的缺陷是不论是页锁还是行锁,加锁的时间可能会很长,这样可能会长时间的限制其他用户的访问,也就是说悲观锁的并发访问性不好。与悲观锁相反,乐观锁则认为其他用户企图改变你正在更改的对象的概率是很小的,因此乐观锁直到你准备提交所作的更改时才将对象锁住,当你读取以及改变该对象时并不加锁。可见乐观锁加锁的时间要比悲观锁短,乐观锁可以用较大的锁粒度获得较好的并发访问性能。但是如果第二个用户恰好在第一个用户提交更改之前读取了该对象,那么当他完成了自己的更改进行提交时,数据库就会发现该对象已经变化了,这样,第二个用户不得不重新读取该对象并作出更改。这说明在乐观锁环境中,会增加并发用户读取对象的次数。
从数据库厂商的角度看,使用乐观的页锁是比较好的,尤其在影响很多行的批量操作中可以放比较少的锁,从而降低对资源的需求提高数据库的性能。再考虑聚集索引。在数据库中记录是按照聚集索引的物理顺序存放的。如果使用页锁,当两个用户同时访问更改位于同一数据页上的相邻两行时,其中一个用户必须等待另一个用户释放锁,这会明显地降低系统的性能。interbase和大多数关系数据库一样,采用的是乐观锁,而且读锁是共享的,写锁是排他的。可以在一个读锁上再放置读锁,但不能再放置写锁;你不能在写锁上再放置任何锁。锁是目前解决多用户并发访问的有效手段。


memcached于1.2.4版本新增CAS(Check and Set)协议类同于Java并发的CAS(Compare and Swap)原子操作,处理同一item被多个线程更改过程的并发问题。

在Memcached中,每个key关联有一个64-bit长度的long型惟一数值,表示该key对应value的版本号。这个数值由Memcached server产生,从1开始,且同一Memcached server不会重复。在两种情况下这个版本数值会加1:1、新增一个key-value对;2、对某已有key对应的value值更新成功。删除item版本值不会减小。
即使用版本号记录进入临界区时读的值是否被修改,以决定当前修改是否生效。
例如
Java代码 
MemcachedClient client = new MemcachedClient(); 
   client.set("fKey", "fValue");  
  //第一次set, 在Memcached server中会维护fKey对应的value的版本号,假设是548; 
 
   client.set("fKey", "sValue");  
  //再次set,则这个fKey对应的value的版本号变为549; 
 
   CASValue casValue = client.gets("fKey"); 
  //这样就可以得到对应key的cas版本号和实际value(各个Memcached client都有类似的对象表示,名字可能不一样,但效果类同),如 casValue.getValue = "sValue",casValue.getCas=549; 


CAS协议解决的问题

模拟多个Memcached client并发set同一个key的场景。如clientA想把当前key的value set为"x",且操作成功;clientB却把当前key的value值由"x"覆盖set为"y",这时clientA再根据key去取value时得到"y"而不是期望的"x",它使用这个值,但不知道这个值已经被其它线程修改过,就可能会出现问题。

CAS协议解决这种并发修改问题。有线程试图修改当前key-value对的value时,先由gets方法得到item的版本号,操作完成提交数据时,使用cas方法谨慎变更,如果在本地对item操作过程中这个key-value对在Memcached server端被其它线程更改过,就放弃此次修改(乐观锁概念)。

原文见:http://blog.csdn.net/zhang_shuai_2011/article/details/8616862

分享到:
评论

相关推荐

    面试必备之乐观锁与悲观锁.rar

    1. **事务隔离级别**:乐观锁和悲观锁与数据库的事务隔离级别密切相关。例如,读未提交(READ UNCOMMITTED)、读已提交(READ COMMITTED)、可重复读(REPEATABLE READ)和串行化(SERIALIZABLE)这四种隔离级别都会...

    后端开发开发技巧总结与入门常用的技巧总结.docx

    并发控制:理解并合理应用锁机制(如乐观锁、悲观锁),防止并发问题。 缓存策略:在合适的地方引入缓存机制(如Redis、Memcached)提高系统性能。 分页与批量处理:对于大数据量的处理,采用分页或流式处理,减轻...

    Laravel开发-lock

    - **乐观锁**:假设很少发生冲突,只在更新数据时检查冲突,如版本号或时间戳。 - **悲观锁**:预先获取锁,防止其他进程修改数据,直到事务结束才释放锁。 - **分布式锁**:通过第三方分布式服务实现锁,如Redis...

    java面试题_多线程(68题).pdf

    5. **乐观锁与悲观锁**: - 悲观锁(如`synchronized`关键字):认为数据访问时会发生冲突,所以在读取数据前会先获取锁,确保数据在读写过程中的独占访问。 - 乐观锁(如`java.util.concurrent.atomic`中的原子类...

    2023年B站Java后端面试最全攻略

    - 数据库事务与并发控制:掌握ACID属性,理解乐观锁、悲观锁的差异。 8. **Spring全家桶**: - Spring Core:理解依赖注入(DI)和面向切面编程(AOP),掌握Bean的生命周期管理。 - Spring MVC:使用Spring MVC...

    数据库高并发

    这通常涉及到并发控制机制,如乐观锁、悲观锁、多版本并发控制(MVCC)等。 乐观锁假设大多数操作不会引起冲突,只在更新数据时检查是否发生冲突;悲观锁则预先锁定数据,防止其他事务修改。MVCC是一种常用的并发...

    Java架构面试笔试专题资料及经验(含答案)和学习笔记.zip

    Java架构面试笔试专题资料及经验(含答案)和学习笔记: ActiveMQ消息中间件面试专题.pdf Dubbo面试专题及答案(下).pdf Dubbo面试及答案(上).pdf java后端面试题答案.pdf ...面试必备之乐观锁与悲观锁.pdf

    java面试tips 支付宝面试要求.zip

    - **事务与锁**:理解ACID特性,了解行级锁、表级锁、乐观锁、悲观锁等。 - **数据库优化**:掌握SQL优化技巧,了解数据库缓存、分区、分片等高级特性。 7. **框架与中间件** - **Spring框架**:理解IoC和AOP的...

    Java秒杀与抢购模型的架构设计与实现.rar

    - **乐观锁/悲观锁**:防止数据的脏读、幻读,例如使用`version`字段实现乐观锁,或者使用数据库的`SELECT FOR UPDATE`语句实现悲观锁。 3. **分布式协调**: - **分布式ID**:如使用`Snowflake`算法生成全局唯一...

    分布式系统设计分布式系统设计

    -乐观锁与悲观锁:乐观锁假设冲突少,悲观锁假设冲突多,各有适用场景。 10. 容器化与编排: - Docker:轻量级容器技术,便于应用打包和迁移。 - Kubernetes(K8s):容器编排工具,管理容器生命周期,提供弹性...

    面试突击班3.4redis知识讲解.zip

    2. 了解乐观锁与悲观锁的概念,以及Redis如何实现分布式锁。 四、Redis高级特性 1. 模块系统:Redis 4.0引入模块系统,允许扩展新的数据类型和功能。 2. Stream数据类型:提供日志记录和消息队列功能。 3. GEO:...

    学java心得

    深入理解数据库,包括事务管理、数据一致性,以及可能需要的乐观锁或悲观锁策略。此外,了解集群和分布式计算,掌握与其他系统通信的手段,如Web服务(Webservice)。 对于前端开发,JavaScript是必不可少的,即使...

    针对高竞争电商负载的事务处理优化原型系统.zip

    乐观锁和悲观锁是常见的并发控制策略。乐观锁假设冲突较少,仅在提交时检查;悲观锁则在操作开始时锁定资源,防止其他操作。在电商系统中,可根据业务场景选择合适的方法。 2. **数据库优化**:通过索引优化、查询...

    Java并发编程与高并发解决方案(高清视频教程).rar

    乐观锁和悲观锁也是并发控制策略,它们在数据库操作中广泛应用,例如Java的JPA和Hibernate框架。 此外,Java内存模型(JMM)规定了线程如何访问和修改共享变量,确保数据一致性。volatile关键字就是JMM的一部分,它...

    Java常见面试题(含J2EE)

    - **事务与并发控制**:ACID特性,乐观锁与悲观锁,MVCC(多版本并发控制)机制。 - **数据库设计**:范式理论,ER模型到关系模型的转换。 6. **设计模式**: - **常见的23种设计模式**:单例、工厂、建造者、...

    java程序员成长之路.doc

    同时,需要掌握数据库的使用,包括事务设置、脏数据、乐观锁、悲观锁等概念。 此外,需要学习集群、分布式、WebService 等技术,能够与其他系统交换数据。同时,需要学习 JavaScript 和 jQuery,能够实现无刷新的...

    数据库笔试面试题汇总

    6. **并发控制**:锁机制(共享锁、排他锁)、乐观锁与悲观锁的区别,以及死锁的概念和避免方法。 7. **数据库设计**:数据库设计包括需求分析、概念设计、逻辑设计和物理设计,重点是ER模型转换为关系模式。 8. *...

    网络游戏-一种游戏用户数据的数据存储方法.zip

    这通常通过锁机制、乐观锁或悲观锁来实现。 10. 扩展性设计:为应对未来增长,游戏数据存储系统应具备良好的扩展性,能够无缝添加新的服务器或调整存储资源。 综上所述,网络游戏中的用户数据存储方法是一个涉及多...

    大型分布式网站架构设计与实践。带目录书签

    8. 并发控制:分布式事务处理需要解决并发一致性问题,例如两阶段提交、乐观锁和悲观锁等策略。 9. 高可用与容错:通过冗余和故障切换机制,如主备模式、集群部署和健康检查,确保系统在部分组件失败时仍能正常运行...

Global site tag (gtag.js) - Google Analytics