Redis基础补充--学习笔记

事务

Redis事务的本质:一组命令的集合

一次性、顺序性、排他性

  • Redis单条命令是保证原子性的,但是事务不保证原子性
  • Redis事务没有隔离级别的概念
    • 所有的命令在事务中,并没有直接被执行,只有发起执行命令的时候才会执行

执行事务

Redis事务包括三个命令:

  • 开启事务multi
  • 命令入队
  • 执行事务exec
连接1:0>multi		#开启事务
"OK"
连接1:0>set k1 v1		#命令入队
"QUEUED"
连接1:0>set k2 v2
"QUEUED"
连接1:0>get k2
"QUEUED"
连接1:0>exec		#执行事务
 1)  "OK"
 2)  "OK"
 3)  "v2"

放弃事务

一旦放弃事务,则之前开启事务后所有的命令入队都失效

连接1:0>multi		#开启事务
"OK"
连接1:0>set k1 v1		#命令入队
"QUEUED"
连接1:0>set k2 v2
"QUEUED"
连接1:0>discard		#放弃事务
"OK"
连接1:0>get k1		#取值失败
null

小结

  • 编译型异常:事务所有的命令都不会被执行
连接1:0>multi
"OK"
连接1:0>set k1 v1
"QUEUED"
连接1:0>getset k2		#事务中故意执行一个错误命令
"ERR wrong number of arguments for 'getset' command"
连接1:0>set k3 v3
"QUEUED"
连接1:0>exec	
"EXECABORT Transaction discarded because of previous errors."
连接1:0>get k1	#事务结束时取不到值,所有的命令都不会被执行
null
  • 运行时异常:如果事务队列中编译通过但是运行时异常,那么在执行命令时其他命令可以正常执行,错误命令会被抛出
连接1:0>multi	#开启事务
"OK"
连接1:0>set k1 v1
"QUEUED"
连接1:0>incr k1	#给字符串自增1,会出错,但是编译时不会报错
"QUEUED"
连接1:0>set k2 v2
"QUEUED"
连接1:0>get k2
"QUEUED"
连接1:0>exec	#执行事务,自增会报错,但是其他命令会被正常执行
 1)  "OK"
 2)  "ERR value is not an integer or out of range"
 3)  "OK"
 4)  "v2"

悲观锁

悲观锁认为什么时候都会出问题,无论做什么都会加锁

由于每次都上锁,导致效率极其低下

乐观锁

乐观锁认为什么时候都不会出问题,所有不会上锁。更新数据时取判断在此期间是否有人修改过这个数据。

正常的情况如下,是可以修改成功的

连接1:0>set money 100
"OK"
连接1:0>set out 0
"OK"
连接1:0>watch money	#监视money
"OK"
连接1:0>multi
"OK"
连接1:0>decrby money 20
"QUEUED"
连接1:0>incrby out 20
"QUEUED"
连接1:0>exec
 1)  "80"
 2)  "20"

但是在执行exec之前,如果另一个线程修改了这些值,这个时候回导致执行失败。

在Redis中watch就相当于乐观锁

对于上述问题,可以先unwatch解锁再加锁watch,然后执行队列,再执行exec

Jedis

Jedis是Redis官方推荐的Java连接开发工具,是使用Java操作Redis的中间件(当然现在不用这个技术了,SpringBoot上可以直接配置)。

首先导入pom依赖

<dependencies>
    <!-- 导入jedis的包-->
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>3.3.0</version>
    </dependency>

    <!--导入fastjson-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.73</version>
    </dependency>
</dependencies>

建立测试类TestPing.java测试连接

public class TestPing {
    
    
    public static void main(String[] args) {
    
    

        Jedis jedis = new Jedis("127.0.0.1",6379);

        System.out.println(jedis.ping());
    }
}
PONG

Process finished with exit code 0

连接成功!

其他的命令和直接在Redis上没什么区别,此处不述

下面主要写一个事务的测试

public class TestPing {
    
    
    public static void main(String[] args) {
    
    

        Jedis jedis = new Jedis("120.26.142.247",6379);

        //开启事务
        Transaction multi = jedis.multi();

        try {
    
    
            multi.set("user1","one");
            multi.set("user2","two");
            multi.exec();
        }catch (Exception e){
    
    
            multi.discard();
            e.printStackTrace();
        }finally {
    
    
            System.out.println(jedis.get("user1"));
            System.out.println(jedis.get("user2"));
            jedis.close();
        }
    }
}

结果如下

one
two

Process finished with exit code 0

猜你喜欢

转载自blog.csdn.net/liuliusix/article/details/108766357