zoukankan      html  css  js  c++  java
  • 五,redis的事务,乐观锁和悲观锁

    事务是什么,我认为事务是不成功,便成仁;

    事务是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。事务由事务开始与事务结束之间执行的全部数据库操作组成。

    但是在redis中,事务中是不存在原子性的。

    一,redis是一群命令的组合,每个命令在一条队列中,顺序执行;

           一个事务中所有的命令都会被序列化,在执行任务的时候,顺序执行。

    二,redis事务没有隔离级别的概念;

    三,redis的三个阶段

          1)开始事务;

          2)命令进入队列;

          3)执行命令。

    四,redis的相关命令

           1)multi 开启事务;

           2)watch key1 ..... keyn,监视一个或者多个key,如果在事务执行之前,被监视的key被其他命令改动,则事务被打断。

           3)exec:执行所有命令;

           4)unwach:取消对所有key的监控;

           5)discard:取消事务,放弃事务块中的所有命令;

    五,指令实例

            1)事务的基本过程

                 开启事务,命令进入序列中,执行命令;

    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379> set name laoli
    QUEUED
    127.0.0.1:6379> set sex boy
    QUEUED
    127.0.0.1:6379> set age 30
    QUEUED
    127.0.0.1:6379> keys *
    QUEUED
    127.0.0.1:6379> exec
    1) OK
    2) OK
    3) OK
    4) 1) "score_ch"
    2) "sex"
    3) "name"
    4) "age"

           2)在事务中,入队的命令中其中有一个命令有错误,事务中所有的命令是不执行的;

           3)在事务中,入队的命令是存在语法性的错误,在执行其他命令时候,其他的命令是可以正常执行的,错误的命令会抛出异常;

    六,悲观锁和乐观锁

           在事务中,事务是有原子性的,事务是可以回滚的;

           但是在redis中,事务是非原子性的,如何让事务有回滚的能力,需要借助wath命令去监控命令去实现。

           1)乐观锁:开启事务前,设置对数据的监听,EXEC时,如果发生数据发生过修改,事务会自动取消(DISCARD)

                               认为什么事情,都不会出现问题,都是乐观的,不会上锁;

      监控money:正常执行;

    127.0.0.1:6379> set money 100
    OK
    127.0.0.1:6379> set out 0
    OK
    127.0.0.1:6379> watch money 
    OK
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379> decrby money 20
    QUEUED
    127.0.0.1:6379> incrby out 20
    QUEUED
    127.0.0.1:6379> exec
    1) (integer) 80
    2) (integer) 20

    如果在监视的money中,发生了变化,则事务会自动取消

    新开一个线程,添加让money变成1000

    127.0.0.1:6379> get money
    "80"
    127.0.0.1:6379> set money 1000
    OK
    127.0.0.1:6379> 

    在开线程之前,首先watch money,然后开始事务,然后新开一个线程,让money变成1000,就是执行上面的代码;然后money减去10元,out添加10元,exec后,出现nil

    127.0.0.1:6379> get money
    "80"
    127.0.0.1:6379> watch money
    OK
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379> decrby money 10
    QUEUED
    127.0.0.1:6379> incrby out 10
    QUEUED
    127.0.0.1:6379> exec
    (nil)

    上面的案例可以看出,乐观锁在监控到元素发生变化是,取消操作;

    解决办法是,放弃监视,重新执行;

    127.0.0.1:6379> UNWATCH
    OK
    127.0.0.1:6379> watch money
    OK
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379> decrby money 10
    QUEUED
    127.0.0.1:6379> incrby out 10
    QUEUED
    127.0.0.1:6379> exec
    1) (integer) 990
    2) (integer) 30

     2)悲观锁

            认为任何事情,都会出现问题,都是悲观的,很消耗性能;

           我们在sql中使用的for update,应用程序的层面手工实现数据加锁保护操作

  • 相关阅读:
    201805140815_《缓存操作函数封装》
    201802071223_《更换两个二进制》
    201801301359——《注意Javascript这种形式》
    201708310807_《算法-Javascript实现最大公约数》
    重拾java openjdk1.8 语法小试
    代码轮子之很简单但是挺管用的基于C# Task的模拟并发的代码
    docker1.12 安装pxc(Percona XtraDB Cluster )测试
    .net orm比较之dapper和Entity Framework6的简单测试比较
    StackExchange.Redis使用和封装小试
    docker1.12 安装redis3官方集群 攻略
  • 原文地址:https://www.cnblogs.com/invban/p/14206467.html
Copyright © 2011-2022 走看看