文档章节

分布式缓存--序列3--原子操作与CAS乐观锁

果子核
 果子核
发布于 2017/06/04 13:56
字数 887
阅读 3
收藏 1
点赞 0
评论 0

 

标签: memcachedcasrediswatch乐观锁

问题的提出

我们知道,在单机的“线程模型“中,2个线程并发修改一个变量,是需要加锁的。这个在Java并发编程–序列1已经讲过,要么是悲观锁,要么是乐观锁。 
这里写图片描述

如果把单机的线程模型,改成有客户端/服务器的进程模型。服务器可以是MySQL/Redis/Memcached任何一种,那该问题又如何解决呢?

这里写图片描述

方案1 – 单条命令的原子性

Mysql: 用类似update table set x = x + 1 where … 这样的单条语句就可解决上述问题,因为服务器内部会处理加锁的问题,不用客户端解决。

Memcached: incr/decr命令

Redis: incr/decr命令

一句话:对于这种简单的整数加减的原子操作,只要是1条命令可以搞定,就不需要客户端解决互斥问题。

方案2 – Memcached/Redis的乐观锁

上面的方案1,必须是单条命令,但该方法有很大局限性。很多时候,如果我们需要执行复杂的计算逻辑,要先把数据get出来,执行复杂逻辑,再set回去。类似下面这种:

//客户端1
x = get(key)
对x执行复杂逻辑
set(key,x)

//客户端2
x = get(key)
对x执行复杂逻辑
set(key,x)
  •  

此时有2条指令,没有办法保证2条语句的原子性,这个时候如何解决呢?

Mysql的乐观锁

关于Mysql解决上述问题的乐观锁方案,此处不再详述,参见Java并发编程-序列1

Memcached乐观锁

Memcached提供了2个命令 gets + cas。gets取出数据的时候,同时返回版本号;修改之后, cas回去的时候,会比较该版本号和服务器上最新的版本号。如果不等,则cas失败。

Redis乐观锁

Redis提供了watch命令,如下所示:

    watch  key1   //修改数据之前,执行watch,意思监听此key

    multi
    set key1  foo  //如果别的客户端在此期间修改了该key1,此处更新将失败
    exec 
  •  

方案3 – Redis事务

Redis也提供了事务的概念,但它不能回滚。如果1条命令执行错误,会继续执行下面的。

      multi

      get foo

      ...

      incr foo

      exec
  •  

此处的multi/extc,类似Mysql中的beganTransaction/endTransaction。 
另外,由于redis是单线程的,因此事务里面的多条语句执行时,不会被打断。

Memcached的多线程 vs. Redis单线程

我们都知道, Memcached内部是多线程的,而Redis是单线程的。多线程好理解,但Redis为什么要搞成单线程呢? 
个人认为,有以下几个原因: 
(1)redis有各种复杂的数据结构list, has, set。也就是说,对于一个(key, value),value的类型可以是list, hash, set。在实际应用场景中,很容易出现多个客户端对同一个key的这个复杂的value数据结构进行并发操作,如果是多线程,势必要引入锁,而锁却是性能杀手。 
相比较而言,memcached只有简单的get/set/add操作,没有复杂数据结构,在互斥这个问题上,没有redis那么严重。

(2)对于纯内存操作来说,cpu并不是瓶颈,瓶颈在网络IO上。所以即使单线程,也很快。另外,如果要利用多核的优势,可以在一个机器上开多个redis实例。

本文转载自:http://blog.csdn.net/chunlongyu/article/details/53346436

共有 人打赏支持
果子核
粉丝 2
博文 39
码字总数 10055
作品 0
海淀
程序员
高并发系统中的常见问题

本文一共分析了三个案例,分别介绍并发系统中的共享资源并发访问、计算型密集型任务缓存访问 、单一热点资源峰值流量问题和解决方案。 Q1:订票系统,某车次只有一张火车票,假定有1w个人同时...

fzxu_05
2015/10/14
29
0
多线程之:java的CAS操作的相关信息

一:锁机制存在的性能问题? 在JDK 5之前Java语言是靠synchronized关键字保证同步的,这会导致有锁(后面的章节还会谈到锁)。 锁机制存在以下问题: (1)在多线程竞争下,加锁、释放锁会导...

无信不立
2016/07/20
0
0
非阻塞同步算法与CAS(Compare and Swap)无锁算法

锁(lock)的代价 锁是用来做并发最简单的方式,当然其代价也是最高的。内核态的锁的时候需要操作系统进行一次上下文切换,加锁、释放锁会导致比较多的上下文切换和调度延时,等待锁的线程会...

空云万里晴
2016/06/16
63
0
Java并发机制及锁的实现原理

Java并发编程概述 并发编程的目的是为了让程序运行得更快,但是,并不是启动更多的线程就能让程序最大限度地并发执行。在进行并发编程时,如果希望通过多线程执行任务让程序运行得更快,会面...

烂猪皮
05/11
0
0
java中的乐观锁的研究总结

前段时间有人问我java中的乐观锁和悲观锁的问题,我被问愣神了,乐观锁和悲观锁我到是听说过,在数据库里面应用极广,但是java里面就好像没有听说过,后来我详细去看了下《java编程思想》,的...

双月通天
2016/06/06
1K
1
Java CAS操作的ABA问题

CAS介绍 比较并交换(compare and swap, CAS),是原子操作的一种,可用于在多线程编程中实现不被打断的数据交换操作,从而避免多线程同时改写某一数据时由于执行顺序不确定性以及中断的不可预...

ksfzhaohui
2016/11/22
1K
4
无锁的同步策略——CAS操作详解

1. 从乐观锁和悲观锁谈起 乐观锁和悲观锁是两种不同的解决并发问题的策略。悲观锁策略假定任何一次并发都会发生冲突,所以总是采用最严格的方式来进行并发控制。java中的独占锁(synchronized...

takumiCX
07/14
0
0
Java原子操作的实现原理

原子操作的实现原理 引言 原子(atom)本意是“不能被进一步分割的最小粒子”,而原子操作(atomic operation)意为“不可被中断的一个或一系列操作”。在多处理器上显示原子操作就有点复杂。本文...

放了一周的酸梅汤
2017/11/09
0
0
线程进阶:多任务处理(17)——Java中的锁(Unsafe基础)

1. 概述 本专题在之前的文章中详细介绍了Java中最常使用的一种锁机制——同步锁。但是同步锁肯定是不适合在所有应用场景中使用的。所以从本文开始,笔者将试图通过两到三篇文章的篇幅向读者介...

yinwenjie
2017/06/14
0
0
聊聊并发(五)原子操作的实现原理

原子(atom)本意是“不能被进一步分割的最小粒子”,而原子操作(atomic operation)意为”不可被中断的一个或一系列操作” 。在多处理器上实现原子操作就变得有点复杂。本文让我们一起来聊...

陶邦仁
2015/03/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Java基础——异常

声明:本栏目所使用的素材都是凯哥学堂VIP学员所写,学员有权匿名,对文章有最终解释权;凯哥学堂旨在促进VIP学员互相学习的基础上公开笔记。 异常处理: 可以挖很多个陷阱,但是不要都是一样...

凯哥学堂
29分钟前
0
0
180723-Quick-Task 动态脚本支持框架之结构设计篇

文章链接:https://liuyueyi.github.io/hexblog/2018/07/23/180723-Quick-Task-动态脚本支持框架之结构设计篇/ Quick-Task 动态脚本支持框架之结构设计篇 相关博文: 180702-QuickTask动态脚本...

小灰灰Blog
33分钟前
0
0
SBT 常用开发技巧

SBT 一直以来都是 Scala 开发者不可言说的痛,最主要的原因就是官方文档维护质量较差,没有经过系统的、循序渐进式的整理,导致初学者入门门槛较高。虽然也有其它构建工具可以选择(例如 Mill...

joymufeng
37分钟前
0
0
HBase in Practice - 性能、监控及问题解决

李钰(社区ID:Yu Li),阿里巴巴计算平台事业部高级技术专家,HBase开源社区PMC&committer。开源技术爱好者,主要关注分布式系统设计、大数据基础平台建设等领域。连续4年基于HBase/HDFS设计和...

中国HBase技术社区
38分钟前
1
0
ES18-JAVA API 批量操作

1.批量查询 Multi Get API public static void multiGet() {// 批量查询MultiGetResponse response = getClient().prepareMultiGet().add("my_person", "my_index", "1")// 查......

贾峰uk
42分钟前
0
0
SpringBoot2.0使用health

1,引入actuator <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency> 2,application.properties ......

暗中观察
49分钟前
0
0
阿里巴巴Java开发规约

###编程规约 命名风格 【强制】代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束 【强制】代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。...

简心
54分钟前
0
0
如何用TypeScript来创建一个简单的Web应用

转载地址 如何用TypeScript来创建一个简单的Web应用 安装TypeScript 获取TypeScript工具的方式: 通过npm(Node.js包管理器) npm install -g typescript 构建你的第一个TypeScript文件 创建...

durban
59分钟前
0
0
分享好友,朋友圈自定义分享链接无效

这个问题是微信6.5.6版本以后,修改了分享规则:分享的连接必须在公众号后台设定的js安全域名内

LM_Mike
今天
0
0
2018年7月23日课程

一、LVS-DR介绍 director分配请求到不同的real server。real server 处理请求后直接回应给用户,这样director负载均衡器仅处理客户机与服务器的一半连接。负载均衡器仅处理一半的连接,避免了...

人在艹木中
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部