Optimistic locking using check-and-set(乐观锁)

乐观锁介绍:
watch指令在redis事物中提供了CAS的行为。为了检测被watch的keys在是否有多个clients同时改变引起冲突,这些keys将会被监控。如果至少有一个被监控的key在执行exec命令前被修改,整个事物将会回滚,不执行任何动作,从而保证原子性操作,并且执行exec会得到null的回复。

乐观锁工作机制:
watch 命令会监视给定的每一个key,当exec时如果监视的任一个key自从调用watch后发生过变化,则整个事务会回滚,不执行任何动作。注意watch的key是对整个连接有效的,事务也一样。如果连接断开,监视和事务都会被自动清除。当然exec,discard,unwatch命令,及客户端连接关闭都会清除连接中的所有监视。还有,如果watch一个不稳定(有生命周期)的key并且此key自然过期,exec仍然会执行事务队列的指令。

客户端1 客户端2 说明
redis 127.0.0.1:6379> get age
"10"
redis 127.0.0.1:6379> get name
"zhangsan"

redis 127.0.0.1:6379> get age
"10"
redis 127.0.0.1:6379> get name
"zhangsan"
数据库中两客户端登录,及键初始值。
redis 127.0.0.1:6379> multi
OK
redis 127.0.0.1:6379> incr age
QUEUED
redis 127.0.0.1:6379> set name lisi
QUEUED
  此时,客户端1开启事务,并提交队列命令:
1.想要将当前age自增+1运算;
2.将name值改为lisi
  redis 127.0.0.1:6379> incr age
(integer) 11

此时,客户端2修改了age值
redis 127.0.0.1:6379> exec
1) (integer) 12
2) OK

redis 127.0.0.1:6379> get name
"lisi"

  此时,客户端1执行队列命令,发现运算之后age不是理想中的11,而是12原因是被其它客户插足抢先给修改了。name值也修改了。这样可能导致数据不一致性...

为了解决这个问题引入“乐观锁”的机制:

     
     
客户端1-引入“乐观锁”机制 客户端2 说明
redis 127.0.0.1:6379> get age
"10"
redis 127.0.0.1:6379> get name
"zhangsan"

redis 127.0.0.1:6379> get age
"10"
redis 127.0.0.1:6379> get name
"zhangsan"
数据库中两客户端登录,及键初始值。
redis 127.0.0.1:6379> watch age name
OK
redis 127.0.0.1:6379> multi
OK
redis 127.0.0.1:6379> incr age
QUEUED
redis 127.0.0.1:6379> set name lisi
QUEUED
  此时,客户端1用watch命令监视age和name,然后开启事务,并提交队列命令
  redis 127.0.0.1:6379> incr age
(integer) 11

此时,客户端2修改了age值
redis 127.0.0.1:6379> exec
(nil)
redis 127.0.0.1:6379> get age
"11"
redis 127.0.0.1:6379> get name
"zhangsan"
  此时,客户端1执行队列命令,由watch监控发现此期间age的值已经被修改过,则让事整个务回滚,不做任何动作。

watch可以同时监控多个键,在监控期间只要有一个键被其它客户端改变,则整个事务回滚。

     

redis的高级事务CAS(乐观锁)的更多相关文章

  1. Redis中的事务及乐观锁的实现

    介绍 Redis中的事务(transaction)是一组命令的集合.     事务同命令一样都是Redis最小的执行单位,一个事务中的命令要么都执行,要么都不执行.     Redis事务的实现需要用 ...

  2. Java性能 -- CAS乐观锁

    synchronized / Lock / CAS synchronized和Lock实现的同步锁机制,都属于悲观锁,而CAS属于乐观锁 悲观锁在高并发的场景下,激烈的锁竞争会造成线程阻塞,而大量阻塞 ...

  3. redis事务和乐观锁

    1 MULTI/EXEC 执行本事务. MULTI set foo bar get foo set foo hello EXEC 在EXEC执行前,三条命令都放入队列中,然后EXEC触发执行.没有回滚 ...

  4. [数据库锁机制] 深入理解乐观锁、悲观锁以及CAS乐观锁的实现机制原理分析

    前言: 在并发访问情况下,可能会出现脏读.不可重复读和幻读等读现象,为了应对这些问题,主流数据库都提供了锁机制,并引入了事务隔离级别的概念.数据库管理系统(DBMS)中的并发控制的任务是确保在多个事务 ...

  5. Redis 事物、悲观、乐观锁 (详细)

    1,概论 事物这东西相信大家都不陌生吧,在学习Spring,Mybatis等框架中, 只要是涉及到数据存储和修改的,都会有事物的存在, 废话就不多说了下面我们来简单的介绍下Redis事物以及锁. 2, ...

  6. 第四节:Geo类型介绍以及Redis批量操作、事务、分布式锁

    一. Geo类型 1. 类型说明 Geo 是 Redis 3.2 版本后新增的数据类型,用来保存兴趣点(POI,point of interest)的坐标信息.可以实现计算两 POI 之间的距离.获取 ...

  7. Java:CAS(乐观锁)

    本文讲解CAS机制,主要是因为最近准备面试题,发现这个问题在面试中出现的频率非常的高,因此把自己学习过程中的一些理解记录下来,希望能对大家也有帮助. 什么是悲观锁.乐观锁?在java语言里,总有一些名 ...

  8. Redis的“假事务”与分布式锁

    关注公众号:CoderBuff,回复"redis"获取<Redis5.x入门教程>完整版PDF. <Redis5.x入门教程>目录 第一章 · 准备工作 第 ...

  9. 并发之ATOMIC原子操作--CAS乐观锁原理(二)

    1.乐观锁介绍 程序完成并发操作时,访问数据时每次不加锁,假设没有冲突去完成某项操作,如果因为冲突失败就重试,直到成功为止.就是当去做某个修改或其他操作的时候它认为不会有其他线程来做同样的操作(竞争) ...

随机推荐

  1. 微信小程序之画布

    canvas 标签默认宽度300px.高度225px 同一页面中的 canvas-id 不可重复,如果使用一个已经出现过的 canvas-id,该 canvas 标签对应的画布将被隐藏并不再正常工作 ...

  2. ASP.NET 日志组件Smart.LogNet.DLL 引用即可写入日志及读取日志

    借助LogNet组件,以后查看站点日志,再也不用去服务器下载了 日志组件:LogNet.DLL ,引用即可使用 写入方法: 1.LogNet.Log.WriteLog("日志标题" ...

  3. XML xmlns

    xmlns xml namespaces 参考 http://www.w3school.com.cn/tags/tag_prop_xmlns.asp http://www.w3school.com.c ...

  4. struts1(一)流程分析

  5. 20170831工作日记--自定义View学习

    学习了LayoutInflater的原理分析.视图的绘制流程.视图的状态及重绘等知识,按类型来划分的话,自定义View的实现方式大概可以分为三种,自绘控件.组合控件.以及继承控件.那么下面我们就来依次 ...

  6. linux 添加本地yum源

    1.查看自己是否安装了 yum rpm -qa|grep yum 查看yum配置文件 2.创建一个文件夹 用于挂载光盘 这里创建到/media下 取名叫cdrom mkdir /media/cdrom ...

  7. POJ3255-Roadblocks(最短路)

    Description Bessie has moved to a small farm and sometimes enjoys returning to visit one of her best ...

  8. MessageFormat.format()和String.format()

    MessageFormat 提供了以与语言无关方式生成连接消息的方式.使用此方法构造向终端用户显示的消息. MessageFormat 获取一组对象,格式化这些对象,然后将格式化后的字符串插入到模式中 ...

  9. 第80讲:List的泛型分析以及::类和Nil对象

    今天我们学习一下scala中的列表,List. 通过源码,我们可以发现,List类型是协变的,所以我们可以把Int类型的List赋值给Any型的List. 我们可以看到,List定义下有3个比较重要的 ...

  10. 用命令行上传本地代码到GitHub

    有两种方式上传,ssh和https,ssh老是报错=.=我用的是https 先下载git   https://git-scm.com/downloads 在代码的文件夹的同级目录中邮件打开git ba ...