zoukankan      html  css  js  c++  java
  • 基于redis的乐观锁实践

    edis真是一个分布式应用场景下的好东西,对于我们的应用设计,功劳大大的!

    今天要研究的是基于redis的事务机制以及watch指令(CAS)实现乐观锁的过程。

    所谓乐观锁,就是利用版本号比较机制,只是在读数据的时候,将读到的数据的版本号一起读出来,当对数据的操作结束后,准备写数据的时候,再进行一次数据版本号的比较,若版本号没有变化,即认为数据是一致的,没有更改,可以直接写入,若版本号有变化,则认为数据被更新,不能写入,防止脏写。

    下面,看看如何基于redis实现乐观锁。

    首先,看看redis的事务,涉及到的指令,主要有multi,exec,discard。而实现乐观锁的指令,在事务基础上,主要是watch指令,以及unwatch指令,unwatch通常可以不用!

    案例1:redis的纯事务

    下面是ssh窗口1里面的操作:

    复制代码
    127.0.0.1:6379> set hello 1
    OK
    127.0.0.1:6379> get hello
    "1"
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379> incr hello
    QUEUED
    127.0.0.1:6379> incr hello                 #这一步执行完毕后,去另外一个窗口(ssh窗口2),对hello这个key做incr操作,将hello对应的值变成2。完成后,继续后面的exec指令
    QUEUED
    127.0.0.1:6379> exec
    1) (integer) 3                             #注意,这时hello的值是3了,前面执行get hello指令时,值是1哟,说明这个值在其他地方被修改过,这里的其他地方,就是指前面提到的,在另外一个连接窗口里面执行的。
    2) (integer) 4
    127.0.0.1:6379>
    复制代码

    这个情景下,multi和exec之间的指令,依然是可以执行的。

    下面的操作,就是在ssh窗口2里面的操作:

    127.0.0.1:6379> 
    127.0.0.1:6379> get hello
    "1"
    127.0.0.1:6379> incr hello
    (integer) 2
    127.0.0.1:6379>

    案例2: 利用watch指令,基于CAS机制,简单的乐观锁

    下面是ssh窗口1里面的操作:

    复制代码
    127.0.0.1:6379> watch hello
    OK
    127.0.0.1:6379> get hello
    "4"
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379> incr hello
    QUEUED
    127.0.0.1:6379> incr hello                #这一步执行完毕后,去另外一个窗口(ssh窗口2),对hello这个key做incr操作,将其值变成5。完成后,继续后面的exec指令
    QUEUED
    127.0.0.1:6379> exec
    (nil)                                     #注意,这是exec执行后返回的是nil,表示事务提交执行失败
    127.0.0.1:6379> 
    127.0.0.1:6379> get hello                 #这个时候,查看hello对应的值,就是在另外一个窗口(ssh窗口2)执行incr后的值
    "5"
    复制代码

    下面是ssh窗口2里面的操作:

    127.0.0.1:6379> incr hello
    (integer) 5
    127.0.0.1:6379> 

    案例3:watch指令在一次事务执行完毕后,即结束其生命周期

    下面是ssh窗口1里面的操作:

    复制代码
    127.0.0.1:6379> multi                     #接着上面案例2后,不再输入watch hello这个指令,直接启动事务
    OK
    127.0.0.1:6379> incr hello
    QUEUED
    127.0.0.1:6379> incr hello                #这一步执行完毕后,就在另外一个窗口(ssh窗口2),执行incr hello,将hello的值变成6。
    QUEUED
    127.0.0.1:6379> exec                      #另外一个窗口(ssh窗口2)里面的操作结束后,继续来这个窗口执行该指令,依然完成了上面的两个incr hello的操作。
    1) (integer) 7
    2) (integer) 8
    127.0.0.1:6379>
    复制代码

    下面是ssh窗口2里面的操作:

    127.0.0.1:6379> incr hello
    (integer) 6
    127.0.0.1:6379>

    上述3个案例的操作,指令其实非常的少,两个窗口的指令全集,截图如下:

    在另外一个窗口(ssh窗口2)中的操作:

    通过这个简单的例子,基于redis的乐观锁,可以得出一个结论:

    1. 乐观锁的实现,必须基于WATCH,然后利用redis的事务。

    2. WATCH生命周期,只是和事务关联的,一个事务执行完毕,相应的watch的生命周期即结束。

    转载:https://www.baidu.com/link?url=lMo3SLlWGSMxGT_nv64y6EYr-p35uOr-8Vp4dtEURh7GSexKS11wLm53hZ-4Omnp9snWHPr0jAGrWU-b5LYYHa&wd=&eqid=f3667c5000056736000000055a66979c

  • 相关阅读:
    NFC读写电子便签总结
    对字符串md5加密
    把ArrayList集合中的字符串内容写到文本文件中
    【原创】关于jquery实现格式化时间
    jQuery插件之ajaxFileUpload
    jxl读取excel实现导入excel写入数据库
    jxl写入excel实现数据导出功能
    多个Jar包的合并操作
    基于git的源代码管理模型——git flow
    Google Gson 使用简介
  • 原文地址:https://www.cnblogs.com/qq1069284034/p/8334449.html
Copyright © 2011-2022 走看看