【Redis笔记-8】Redis事务及其Java实现

来源:互联网 发布:ubuntu 16.04安装lamp 编辑:程序博客网 时间:2024/06/05 16:29

0.本文目录

  • 本文目录
  • 开篇明志
  • 事务
    • 1 事务概念
    • 2 两类错误
  • WATCH命令
  • Java实现

1.开篇明志

本文将介绍Redis事务。


2.事务

2.1 事务概念

Redis中的事务是一组命令的集合。一个事务中的命令要么都执行,要么都不执行。

这里写图片描述

127.0.0.1:6379> MULTI    //告诉Redis 后面会有多条命令同属一个事物,将命令加入队列OK127.0.0.1:6379> SET A 1QUEUED  //说明  SET A 1 进入事物队列了127.0.0.1:6379> SET B 2QUEUED  //说明  SET B 1 进入事物队列了127.0.0.1:6379> EXEC    //高如Redis顺序依次执行方才缓存的命令1) OK   //执行命令的返回值2) OK   //执行命令的返回值127.0.0.1:6379> GET A"1"127.0.0.1:6379> GET B"2"

Redis保证了事物中的所有命令要么都执行,要么都不执行。如果在执行EXEC命令之前客户端断线了,则Redis会清空事务队列, 事务中的所有命令都不会执行。

此外,Redis事务保证命令一次执行, 先进入事务队列的命令先执行, 后进入食物队列的命令后执行。

2.2 两类错误

在事务中,多条语句中的一条如果有错误,那么会怎么样呢?

来我们一起来做个试验

  • 语法错误

这里写图片描述

127.0.0.1:6379> MULTIOK127.0.0.1:6379> SET C 3QUEUED127.0.0.1:6379> SET(error) ERR wrong number of arguments for 'set' command127.0.0.1:6379> GET(error) ERR wrong number of arguments for 'get' command127.0.0.1:6379> EXEC(error) EXECABORT Transaction discarded because of previous errors.127.0.0.1:6379> 

可以看到,如果中间有错误,Redis会直接返回错误, 不执行任何操作 discarded

  • 运行错误
    运行错误指在命令执行时出现的错误,比如使用散列类型的命令操作集合类型的键,这种错误在实际执行之前Redis是无法发现的,所以在事务里这样的命令是会被Redis接受并执行的。如果事务里的一条命令出现了运行错误,事务里其他的命令依然会继续执行(包括出错命令之后的命令)

SADD key member [member …]
将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略。
假如 key 不存在,则创建一个只包含 member 元素作成员的集合。
当 key 不是集合类型时,返回一个错误。


这里写图片描述

127.0.0.1:6379> MULTIOK127.0.0.1:6379> SET KEY 1QUEUED127.0.0.1:6379> SADD KEY 2QUEUED127.0.0.1:6379> SET KEY 3QUEUED127.0.0.1:6379> EXEC1) OK2) (error) WRONGTYPE Operation against a key holding the wrong kind of value3) OK127.0.0.1:6379> 

Redis 的事务没有关系数据库事务提供的回滚(rollback)功能。为此开发者必须在事务执行出错后自己收拾剩下的摊子(将数据库复原会事务执行前的状态)

3.WATCH命令

有时需要根据前一条命令执行的返回值,来决定下一条命令是否执行,这时候就用法哦WATCH命令。它可以监控一个或多个键, 一旦其中一个键被修改或者删除,之后的事务就不会执行。

由于WATCH命令的作用只是当被监控的键值被修改后组织之后一个事务的执行,而不能保证其他客户端不修改这一键值, 所以我们需要在EXEC执行失败后重新执行整个事务函数。

这里写图片描述

127.0.0.1:6379> SET KEY 1OK127.0.0.1:6379> WATCH KEYOK127.0.0.1:6379> SET KEY 2OK127.0.0.1:6379> GET KEY"2"127.0.0.1:6379> MULTIOK127.0.0.1:6379> SET KEY 3QUEUED127.0.0.1:6379> EXEC(nil)127.0.0.1:6379> GET KEY"2"127.0.0.1:6379>

Java实现

    @Test      public void testTansaction() {          Jedis jedis = new Jedis("127.0.0.1");          Transaction transaction = jedis.multi();          transaction.lpush("key", "11");          transaction.lpush("key", "22");            List<Object> list = transaction.exec();         System.out.println(jedis.lrange("key",0,10));      }  //打印输出结果如下[22, 11]

下面来一个运行中报错:

    @Test      public void testTansaction2() {          Jedis jedis = new Jedis("127.0.0.1");          try {              Transaction transaction = jedis.multi();              transaction.lpush("QQ", "55");              int make_error = 1 / 0;             transaction.lpush("QQ", "66");              List<Object> list = transaction.exec();          } catch (Exception e) {              e.printStackTrace();        }      }  
java.lang.ArithmeticException: / by zero    at com.springmvc.redis.JedisTest.testTansaction2(JedisTest.java:54)    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)..........

通过数据库查看之后,发现整个事务并没有执行,因为中间出现异常退出了。

原创粉丝点击