• 使用Java操作Redis事务


    事务

    Redis 事务可以一次执行多个命令,有两个特性:
    • 隔离性:事务的所有命令都会序列化、按顺序的执行,事务执行完后才会执行其他客服端的命令。

    • 原子性: 事务中的命令要么全部被执行,要么全部不执行。

    使用你事务时会遇到两个错误:
    • 入队时出错,一般时因为语法错误引起的,加入事务队列就会报错,遇到这类错误,一般会放弃事务

    • EXEC调用后出错,列如对一个 值为 a1key 执行 incr,这类错误,即使某个命令产生了错误,其他命令依旧会继续执行执行,不会回滚

    Reids 中的 WATCH命令

    使用 WATCH 命令可以监控键,如果被监控的键,再 EXEC 之前被修改,那么事务会放弃执行(注意:事务中的命令在 exec命令后才开始执行)

    EXEC 执行以后,无论事务是否执行成功,都会放弃对所有键的监控。

    使用Java操控Redis事务命令
    // 开启事务
    Transaction transaction = jedis.multi();
    // 提交事务
    transaction.exec();
    // 放弃事务
    transaction.discard();
    // 监控键
    jedis.watch("balance", "debt");
    // 放弃所有被监控的键
    jedis.unwatch();
    

    完整代码示例:

    package com.project.test;
    
    import java.util.List;
    
    import org.junit.Before;
    import org.junit.Test;
    
    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.Transaction;
    
    /**
     * Rdis 事务
     *
     */
    public class TestTX {
        
        static final Jedis jedis = new Jedis("132.232.6.208", 6381);
        /**
         * 清空数据库
         */
        @Before
        public void flushdb() {
            jedis.flushDB();
        }
        
        @Test
        public void commitTest() {
            
            // 开启事务
            Transaction transaction = jedis.multi();
            
            transaction.set("key-1", "value-1");
            transaction.set("key-2", "value-2");
            transaction.set("key-3", "value-3");
            transaction.set("key-4", "value-4");
            
            // 提交事务
            transaction.exec();
            
            System.out.println(jedis.keys("*"));
        }
        
        
        @Test
        public void discardTest() {
            
            // 开启事务
            Transaction transaction = jedis.multi();
            
            transaction.set("key-1", "value-1");
            transaction.set("key-2", "value-2");
            transaction.set("key-3", "value-3");
            transaction.set("key-4", "value-4");
            
            // 放弃事务
            transaction.discard();
            
            System.out.println(jedis.keys("*"));
        }
        
        /**
         * watch 命令会标记一个或多个键
         * 如果事务中被标记的键,在提交事务之前被修改了,那么事务就会失败。
         * @return 
         * @throws InterruptedException 
         */
        @Test
        public void watchTest() throws InterruptedException {
            boolean resultValue = transMethod(10);
            System.out.println("交易结果(事务执行结果):" + resultValue);
            
            int balance = Integer.parseInt(jedis.get("balance"));
            int debt = Integer.parseInt(jedis.get("debt"));
            
            System.out.printf("balance: %d, debt: %d
    ", balance, debt);
        }
        
        // 支付操作
        public static boolean transMethod(int amtToSubtract) throws InterruptedException {
            int balance;  // 余额
            int debt;  // 负债
            
            jedis.set("balance", "100");
            jedis.set("debt", "0");
            
            jedis.watch("balance", "debt");
            
            balance = Integer.parseInt(jedis.get("balance"));
            
            // 余额不足
            if (balance < amtToSubtract) {
                jedis.unwatch();  // 放弃所有被监控的键
                System.out.println("Insufficient balance");
                
                return false;
            }
            
            Transaction transaction = jedis.multi();
            // 扣钱
            transaction.decrBy("balance", amtToSubtract);
            Thread.sleep(5000);  // 在外部修改 balance 或者 debt
            transaction.incrBy("debt", amtToSubtract);
            
            // list为空说明事务执行失败
            List<Object> list = transaction.exec();
            
            return !list.isEmpty();
        }
    }
    
  • 相关阅读:
    select(Linux 编程)
    Amazon DynamoDB, 面向互联网应用的高性能、可扩展的NoSQL数据库
    键值表
    工厂方法模式之C++实现
    spring(16)------spring的数据源配置
    LeetCode 206 Reverse Linked List(反转链表)(Linked List)(四步将递归改写成迭代)(*)
    地图之CLLocationManager的使用 定位功能使用
    正则则表达式大全(收集)
    文件的读取和写入(指定路径)
    二维码(带有图片)的生成
  • 原文地址:https://www.cnblogs.com/47Gamer/p/13727431.html
Copyright © 2020-2023  润新知