Redis-事务

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zanpengfei/article/details/84995010

1、Redis 的事务使用非常简单,也因为这种简单性,它的事务模型很不严格,这要求我们不能像使用关系数据库的事务一样来使用 Redis。

2、每个事务的操作都有begin、commit 和 rollback,Redis也不例外,也包括multi/exec/discard。multi 指示事务的开始,exec 指示事务的执行,discard 指示事务的丢弃,如下图所示:

  • 3、原子性:指要么事物都成功,要么全部失败,但Redis的事务仅仅满足事务的个理性,隔离性肿的窜行化——当前的执行的事务有着不被其他事务打断的权利,如下图所示:

4、discard(丢弃):用于丢弃事务缓存队列中的所有指令,在 exec 执行之前

5、Watch:Redis在处理并发时,通常会使用分布式锁,但分布式锁是一种悲观锁,可以使用另外一种方式,Watch,该指令是一种乐观锁:

1)watch 会在事务开始之前盯住 1 个或多个关键变量,当事务执行时,也就是服务器收到了 exec 指令要顺序执行缓存的事务队列时,Redis 会检查关键变量自 watch 之后,是否被修改了 (包括当前事务所在的客户端)。如果关键变量被人动过了,exec 指令就会返回 null ,通知客户端事务执行失败,客户端可以选择重试等操作

2)Redis 禁止在 multi 和 exec 之间执行 watch 指令,而必须在 multi 之前做好盯住关键变量,否则会出错。

3)通过watch命令来实现余额加倍的实现:

import java.util.List;

import redis.clients.jedis.Jedis;

import redis.clients.jedis.Transaction;

public class TransactionDemo {

      public static void main(String[] args) {

           Jedis jedis = new Jedis(); String userId = "abc";

         String key = keyFor(userId); jedis.setnx(key, String.valueOf(5));

# setnx 做初始化

      System.out.println(doubleAccount(jedis, userId));

     jedis.close();

       }

public static int doubleAccount(Jedis jedis, String userId) {

        String key = keyFor(userId); while (true) {

       jedis.watch(key);

      int value = Integer.parseInt(jedis.get(key));

      value *= 2;

     // 加倍

     Transaction tx = jedis.multi();

     tx.set(key, String.valueOf(value));

    List res = tx.exec(); if (res != null) {

   break;
  // 成功了

   }

     }

  return Integer.parseInt(jedis.get(key));

  // 重新获取余额

       }

 public static String keyFor(String userId) {

     return String.format("account_%s", userId);

    }

 }

猜你喜欢

转载自blog.csdn.net/zanpengfei/article/details/84995010