Redis事务介绍

Redis事务

Redis事务介绍

  • 首先我们需要知道一点,Redis是弱事务类型的,以下是对它的常见介绍
    • 1.Redis的事务是通过MULTI、EXEC、DISCARDWATCH这四个命令来完成的。
    • 2.Redis的单个命令都是原子性的,所以这里需要确保事务性的对象是命令集合
    • 3.Redis将命令集合序列化并确保处于同一事物的命令集合连续切不被打断的执行。
    • 4.Redis不支持回滚操作。

事务命令

MULTI

用于标记事务块的开始。
Redis会将后续的命令诸葛放入队列中,然后使用EXEC命令原子化地执行这个命令序列
简单就是创建了一个事务列表,用于处理Redis弱事务的特性,模拟批次原子操作的提交,不过每个原子操作之间是独立的(合在一起的事务列表不支持原子性),可能会执行成功,也可能会执行失败,相互之间不影响。

客户端1,开启multi,但是还未提交
Redis事务介绍_第1张图片
客户端2,查询刚刚输入的值,查询不到值,显示nil
Redis事务介绍_第2张图片
客户端1提交,执行EXEC后,客户端2可以正常查询到
Redis事务介绍_第3张图片
这里显示两个OK表示两条指令都提交成功,也存在其中没有执行成功的情况,这里就体现了redis弱事务不支持原子性的特性。
在这里插入图片描述
客户端1提交后,客户端2就正常查询到了

EXEC

在一个事务中执行所有先前放入队列的命令,然后回复正常的连接状态

DISCARD

清除所有先前再一个事务中放入队列的命令,然后恢复正常的连接状态

Redis事务介绍_第4张图片
WATCH

当某个【事务需要按条件执行】时,就需要使用这个命令将给定的【键者之谓监控】的状态
简单来说就是监控某个键的状态,如果该值发生了变化,事务列表里的操作就不能执行了,常用来作为乐观锁

Redis事务介绍_第5张图片
客户端1监听q1,监听时候的值为11,然后执行multi,添加了两个键值对,但是还未执行exec提交
在这里插入图片描述
客户端2将q1的值改掉,此时回到客户端1执行exec就会出现下面情况
Redis事务介绍_第6张图片
此时提交会出现nil,这就是watch的效果,常用来做乐观锁

UNWATCH

清除所有先前为一个事务监控的键

在这里插入图片描述
就是清除上一个watch的监控效果

事务失败处理

Redis事务失败存在两种情况

  • Redis语法错误

    整个事务的命令在列表离都清除
    Redis事务介绍_第7张图片
    这里sets q1明显存在语法错误,所以后续exec提交的时候,整个队列中都提交失败

  • Redis运行错误

    在队列里正确的命令可以执行(弱事务性)
    Redis事务介绍_第8张图片

  • Redis为什么不支持事务回滚?

    1. 大多数事务失败是因为语法错误或者类型错误,这两种错误,在开发阶段都是可以避免的
    2. Redis为了性能方面就忽略了事务回滚

Redis事务使用场景-----乐观锁

乐观锁基于CAS(Compare And Swap)思想(比较并替换),时不具有胡持续,不会产生锁等待而小号资源,但是需要反复的重试,但也是因为重试的机制,能比较快的响应,英寸我们能可以利用Redis来实现乐观锁,具体思路如下:

  • 1、利用redis的watch功能,监控这个redisKey的状态值
  • 2、获取redisKey的值
  • 3、创建redis事务
  • 4、给这个key的值+1
  • 5、然后去执行这个事务,如果key的值被修改过则回滚, key不加1
public void watch() {
        try {
            String watchkeys = "'watchkeys";
            //初始值value=1
            jedis. set (watchKeys, 1);
            //监听key为watchKeys的值
            jedis. watch(watchkeys);
            //开启事务
            Transaction tx = jedis.multi();
            //watchkeys自增加一
            tx.incr(watchKeys);
            //执行事务,如果其他线程对watchkeys中的value进行修改,则该事务将不会执行
            //通过redis事务以及watch命令实现乐观锁
            List<object> exec = tx.exec();
            if (exec == nulll) {
                System.out.println("事务未执行");
            } else {
                system.out.println("事务成功执行,watchkeys的value成功修改");
            }
        } catch (Exception e) {
            e.printstackTrace();
        } finally {
            jedis.close();
        }
    }

Redis乐观锁实现秒杀

public static void main(String[] arg) {
        String rediskey = "second";
        ExecutorService executorservice = Executor.newFixedThreadPoo1(20);
        try {
            Jedis jedis = new Jedis("127.0.0.1", 6378);
            //初始值
            jedis.set(rediskey, "0");
            jedis.close();
        } catch (Exception e) {
            e.printstackTrace();
            for (int i = 0; i < 1000; i++) {
                executorservice.execute(()-> {
                        Jedis jedis1 = new Jedis("127.0.0.1",6378);
                try {
                    jedi sl.watch(redisKey);
                    String redisvalue = jedis1.get(rediskey);
                    int valInteger = Integer.valueof(redisvalue);
                    String userInfo = UUID.randomUUID().tostring();
                    //没有秒完
                    if (valInteger < 20) {
                        Transaction tx = jedis1.multi();
                        tx.incr(redisKey);
                        List list = tx.exec();
                        //秒成功 失败返回空list而不是空
                        if (list != nu11 && list.size() > 0) {
                            System.out.println("用户: " + userInfo + ",秒杀成功!当前成功人数:" + (valInteger + 1));
                        }
                        //版本变化,被别人抢了。
                        else {
                            System.out.println("用户:"+ userInfo + ",秒杀失败");
                        }
                    }
                    //秒完了
                    else {
                        System.out.println("已经有20人秒杀成功,秒杀结束");
                    }
                } catch (Exception e) {
                    e.printstackTrace();
                } finally {
                    jedis1.close();
                }
                });
            }
            executorservice.shutdown();
        }
    }

你可能感兴趣的:(大数据,redis)