五,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,应用程序的层面手工实现数据加锁保护操作

 

posted @ 2020-12-29 14:38  木子小僧  阅读(300)  评论(0编辑  收藏  举报