首页 > 数据库 >【Redis】事务和乐观锁如何实现?

【Redis】事务和乐观锁如何实现?

时间:2023-02-01 23:57:12浏览次数:45  
标签:事务 127.0 OK 0.1 Redis 乐观 6379 QUEUED

目录

前言

  • 事务

    在Redis事务没有没有隔离级别的概念!
    在Redis单条命令式保证原子性的,但是事务不保证原子性!

    • ①原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。
    • ②一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
    • ③隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
    • ④持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
  • 乐观锁

    在Redis是可以实现乐观锁的!

    • ①当程序中可能出现并发的情况时,就需要保证在并发情况下数据的准确性,以此确保当前用户和其他用户一起操作时,所得到的结果和他单独操作时的结果是一样的。
    • ②没有做好并发控制,就可能导致脏读、幻读和不可重复读等问题。

Redis如何实现事务?

由以上可以得出结论,Redis是支持单条命令事务的,但是事务并不能保证原子性!

  • 正常执行事务

    127.0.0.1:6379> multi  #开启事务
    OK
    127.0.0.1:6379> set name dingyongjun  #添加数据
    QUEUED
    127.0.0.1:6379> set age 26  #添加数据
    QUEUED
    127.0.0.1:6379> set high 172  #添加数据
    QUEUED
    127.0.0.1:6379> exec  执行事务
    1) OK
    2) OK
    3) OK
    127.0.0.1:6379> get name  #获取数据成功,证明事务执行成功
    "dingyongjun"
    127.0.0.1:6379> get age
    "26"
    
  • 放弃事务

    127.0.0.1:6379> multi  #开启事务
    OK
    127.0.0.1:6379> set name dingyongjun  #添加数据
    QUEUED
    127.0.0.1:6379> set age 26  #添加数据
    QUEUED
    127.0.0.1:6379> discard  #放弃事务
    OK
    127.0.0.1:6379> get name  #不会执行事务里面的添加操作
    (nil)
    
  • 编译时异常,代码有问题,或者命令有问题,所有的命令都不会被执行

    127.0.0.1:6379> multi  #开启事务
    OK
    127.0.0.1:6379> set name dingyongjun  #添加数据
    QUEUED
    127.0.0.1:6379> set age 23  #添加数据
    QUEUED
    127.0.0.1:6379> getset name  #输入一个错误的命令,这时候已经报错了,但是这个还是进入了事务的队列当中
    (error) ERR wrong number of arguments for 'getset' command
    127.0.0.1:6379> set high 173  #添加数据
    QUEUED
    127.0.0.1:6379> exec  #执行事务,报错,并且所有的命令都不会执行
    (error) EXECABORT Transaction discarded because of previous errors.
    127.0.0.1:6379> get name  #获取数据为空,证明没有执行
    (nil)
    
  • 运行时异常,除了语法错误不会被执行且抛出异常后,其他的正确命令可以正常执行

    127.0.0.1:6379> multi  #开启事务
    OK
    127.0.0.1:6379> set name dingyongjun  #添加字符串数据
    QUEUED
    127.0.0.1:6379> incr name  #对字符串数据进行自增操作
    QUEUED
    127.0.0.1:6379> set age 23  #添加数据
    QUEUED
    127.0.0.1:6379> get age  #获取数据
    QUEUED 
    127.0.0.1:6379> exec  #执行事务。虽然对字符串数据进行自增操作报错了,但是其他的命令还是可以正常执行的
    1) OK
    2) (error) ERR value is not an integer or out of range
    3) OK
    4) "23"
    127.0.0.1:6379> get age  #获取数据成功
    "23"
    

Redis如何实现乐观锁?

  • watch(监视)

    127.0.0.1:6379> set money 100  #添加金钱100
    OK
    127.0.0.1:6379> set cost 0  #添加花费0
    OK
    127.0.0.1:6379> watch money  #监控金钱
    OK
    127.0.0.1:6379> multi  #开启事务
    OK
    127.0.0.1:6379> DECRBY money 30  #金钱-30
    QUEUED
    127.0.0.1:6379> incrby cost 30  #花费+30
    QUEUED
    127.0.0.1:6379> exec  #执行事务,成功!这时候数据没有发生变动才可以成功
    1) (integer) 70
    2) (integer) 30
    
  • 多线程测试watch

    #线程1

    #线程1
    127.0.0.1:6379> set money 100  #添加金钱100
    OK
    127.0.0.1:6379> set cost 0  #添加花费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  #金钱-20
    QUEUED
    127.0.0.1:6379> INCRBY cost 20   #花费+20
    QUEUED
    #这里先不要执行,先执行线程2来修改被监视的值
    127.0.0.1:6379> exec  #执行报错,因为我们监视了money这个值,如果事务要对这个值进行操作前
    #监视器会判断这个值是否正常,如果发生改变,事务执行失败!
    (nil)
    

    #线程2

    #线程2,这个在事务执行前操作执行
    127.0.0.1:6379> INCRBY money 20  #金钱+20
    (integer) 120
    

悲观锁与乐观锁

  • 悲观锁: 什么时候都会出问题,所以一直监视着,没有执行当前步骤完成前,不让任何线程执行,十分浪费性能!一般不使用!
  • 乐观锁: 只有更新数据的时候去判断一下,在此期间是否有人修改过被监视的这个数据,没有的话正常执行事务,反之执行失败!

标签:事务,127.0,OK,0.1,Redis,乐观,6379,QUEUED
From: https://www.cnblogs.com/al6nlee/p/17084519.html

相关文章

  • day16-声明式事务-02
    声明式事务-023.事务的传播机制事务的传播机制说明:当有多个事务处理并存时,如何控制?比如用户去购买两次商品(使用不同的方法),每个方法都是一个事务,那么如何控制呢?也......
  • 【Redis】三大特殊数据类型
    目录Geospatial:地理位置Geospatial:地理位置城市经纬度查询:经纬度查询注意点1:两极无法直接添加,我们一般会下载城市数据,直接通过java程序一次性导入!注意点2:有效的......
  • 【Redis】五大数据类型
    目录String(字符串)添加、查询、追加、获取长度,判断是否存在的操作自增、自减操作截取、替换字符串操作设置过期时间、不存在设置操作mset、mget操作添加获取对象、getset操......
  • Spring事务的实现方式和原理以及隔离级别
    事务这个概念是数据库层面的,Spring只是基于数据库中的事务进行了扩展,以及提供了一些能让程序员更加方便操作事务的方式。Spring中有两种使用事务的方式,一种是编程式的,一种......
  • redis-desktop-manager-0.8.0.3844
    redis-desktop-manager-0.8.0.3844下载地址:https://www.aliyundrive.com/s/Y2fobkVjAdF链接:https://pan.baidu.com/s/1keQMs8Tiaj4liE6tgBe82A提取码:nrt4......
  • RedisTemplate和StringRedisTemplate区别
    RedisTemplate和StringRedisTemplate区别StringRedisTemplate继承RedisTemplate主要区别是使用的序列化类不同StringRedisTemplate的API假定所有的数据类型都是字符......
  • 75、缓存---分布式锁---Redisson信号量测试
    可以用来做分布式限流操作。我们在redis中存储一个数据为3@AutowiredRedissonClientredissonClient;@AutowiredStringRedisTemplateredisTemplate......
  • 74、缓存---分布式锁---Redisson闭锁测试
    @AutowiredRedissonClientredissonClient;@AutowiredStringRedisTemplateredisTemplate;//闭锁@GetMapping("/lockDoor")@Response......
  • 73、缓存---分布式锁---Redisson读写锁测试
    保证一定读到最新数据,修改期间,写锁是一个排他锁/互斥锁。读锁是一个共享锁。(相当于操作系统中的读写者问题)写锁没释放读必须等待测试如下:@AutowiredRedissonClient......
  • 72、缓存---分布式锁---Redisson的Lock锁测试
    @GetMapping("/hello")@ResponseBodypublicStringhello(){//1、获取一把锁,只要是锁的名字一样,就是同一把锁RLocklock=redissonClien......