玖叶教程网

前端编程开发入门

聊聊redis的事务操作(redis事务失败怎么处理)

本文主要研究一下redis的事务操作

命令

multi与exec

  • 命令行
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr total
QUEUED
127.0.0.1:6379> incr len
QUEUED
127.0.0.1:6379> exec
1) (integer) 2
2) (integer) 2
127.0.0.1:6379> get total
"2"
127.0.0.1:6379> get len
"2"
  • lettuce实例
 @Test
 public void testMultiExec(){
 RedisClient client = RedisClient.create("redis://192.168.99.100:6379/0");
 StatefulRedisConnection<String, String> connection = client.connect();
 RedisCommands<String, String> syncCommands = connection.sync();
 syncCommands.set("hello","1");
 syncCommands.set("world","2");
 syncCommands.multi();
 syncCommands.incr("hello");
 syncCommands.incr("world");
 //DefaultTransactionResult[wasRolledBack=false,result=[1, 2, 1, 3, 1]]
 TransactionResult transactionResult = syncCommands.exec();
 System.out.println(transactionResult);
 System.out.println(syncCommands.get("hello"));
 System.out.println(syncCommands.get("world"));
 }

部分执行

  • 命令行
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set a hello
QUEUED
127.0.0.1:6379> set b world
QUEUED
127.0.0.1:6379> incr a
QUEUED
127.0.0.1:6379> set c part
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
3) (error) ERR value is not an integer or out of range
4) OK
127.0.0.1:6379> get a
"hello"
127.0.0.1:6379> get b
"world"
127.0.0.1:6379> get c
"part"
  • lettuce实例
 @Test
 public void testMultiExecError(){
 RedisClient client = RedisClient.create("redis://192.168.99.100:6379/0");
 StatefulRedisConnection<String, String> connection = client.connect();
 RedisCommands<String, String> syncCommands = connection.sync();
 syncCommands.multi();
 syncCommands.set("a","hello");
 syncCommands.set("b","world");
 syncCommands.incr("a");
 syncCommands.set("c","part");
 //DefaultTransactionResult[wasRolledBack=false,result=[OK, OK, io.lettuce.core.RedisCommandExecutionException: ERR value is not an integer or out of range, OK, 1]]
 TransactionResult transactionResult = syncCommands.exec();
 System.out.println(transactionResult);
 System.out.println(syncCommands.get("a"));
 System.out.println(syncCommands.get("b"));
 System.out.println(syncCommands.get("c"));
 }

multi与discard

  • 命令行
127.0.0.1:6379> set sum 1
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr sum
QUEUED
127.0.0.1:6379> discard
OK
127.0.0.1:6379> get sum
"1"
  • lettuce实例
 @Test
 public void testMultiDiscard(){
 RedisClient client = RedisClient.create("redis://192.168.99.100:6379/0");
 StatefulRedisConnection<String, String> connection = client.connect();
 RedisCommands<String, String> syncCommands = connection.sync();
 syncCommands.incr("key1");
 syncCommands.multi();
 syncCommands.incr("key1");
 //需要有multi才可以执行discard,成功返回OK
 String result = syncCommands.discard();
 System.out.println(result);
 System.out.println(syncCommands.get("key1"));
 }

check and set

 @Test
 public void testWatch(){
 RedisClient client = RedisClient.create("redis://192.168.99.100:6379/0");
 StatefulRedisConnection<String, String> connection = client.connect();
 RedisCommands<String, String> syncCommands = connection.sync();
 String key = "key";
 syncCommands.watch(key);
 //another connection
 StatefulRedisConnection<String, String> conn2 = client.connect();
 RedisCommands<String, String> syncCommands2 = conn2.sync();
 syncCommands2.set(key, "a");
 syncCommands.multi();
 syncCommands.append(key, "b");
 //DefaultTransactionResult [wasRolledBack=true, responses=0]
 TransactionResult transactionResult = syncCommands.exec();
 System.out.println(transactionResult);
 System.out.println(syncCommands.get(key));
 }

小结

  • reids提供multi exec/discard指令,类似open commit/rollback transaction,不过exec遇到类型操作等错误时不会滚,该成功执行的命令还是成功执行,该失败的还是失败
  • multi exec保证的是,只要exec命令有执行成功,则事务中一系列的命令都能执行,如果exec因为网络等问题,server端没有接收到,则事务中的一系列命令都不会被执行
  • discard需要在有调用multi的前提下才能使用,该命令会清空事务队列等待执行的命令
  • redis提供watch指令,可以配合multi exec来使用,可以实现类似数据库的乐观锁的机制,一旦watch的key被其他client有更新,则整个exec操作失败

doc

  • redis事务

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言