• redis的事务与乐观锁


    例如,我们假设Redis中并未提供incr命令来完成键值的原子性递增,如果要实现该功能,我们只能自行编写相应的代码。其伪码如下:
         val = GET mykey
         val = val + 1

         SET mykey $val


    这个读++写操作,在mysql中是 update xx set i=i+1,redis是incre

    无论是mysql还是redis,其核心都是一致的,即使其成为原子操作过程


    redis的watch提供了这一功能:

    WATCH mykey
         val = GET mykey
         val = val + 1
         MULTI
         SET mykey $val
         EXEC

    将set命令包围在事务中,假设我们通过WATCH命令在事务执行之前监控了多个Keys,倘若在WATCH之后有任何Key的值发生了变化,EXEC命令执行的事务都将被放弃,同时返回Nullmulti-bulk应答以通知调用者事务执行失败。


    http://blog.csdn.net/qw463800202/article/details/53287139


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

    http://www.cnblogs.com/shihuc/p/7284986.html


    另有一个redis的实例:乐观锁秒杀系统

    http://blog.csdn.net/evankaka/article/details/70570200



    客户端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可以同时监控多个键,在监控期间只要有一个键被其它客户端改变,则整个事务回滚。
         

    http://www.cnblogs.com/martinzhang/p/3415204.html


    redis的事务提供了数据隔离级别,可以避免脏读,不能避免幻读和不可重复读


  • 相关阅读:
    关于cocos2dx之lua使用TableView
    设计模式-----工厂模式
    android YUV Sensor配置Camera应用的flash auto菜单
    AngularJS实现cookie跨域
    julia/pyplot 绘图加入标签和标题
    自己写unicode转换ascii码,wchar*到char*
    Android笔记——Activity中的数据传递案例(用户注冊)
    IIS预编译提升载入速度
    Python Tkinter 基础控件学习
    spfile
  • 原文地址:https://www.cnblogs.com/silyvin/p/9106738.html
Copyright © 2020-2023  润新知