后端与系统架构1447 字

Redis支持事务吗?

·全库 413 / 611

《Redis支持事务吗?》共 0.1 万字,通篇围绕 Redis、数据库、场景、并发 展开,归在「后端与系统架构」这一层。

覆盖Redis数据库场景并发架构Kafka

适合给 AI 系统搭底座、要管得住的人

目录骨架(8 节)
  1. Redis 事务概述
  2. 真实案例:Redis支持事务的应用
  3. 事务的规划和优化
  4. 业务亮点
  5. Redis 事务的命令
  6. 需求场景
  7. 代码实现
  8. 如何优化?
目录 · 3 节

Redis 事务概述

Redis 是一个高性能的键值存储系统,支持多种数据结构和操作,其中包括事务功能。虽然 Redis 提供了类似的数据库事务机制,但它与传统数据库的事务机制有所不同。Redis 的事务机制不具备的ACID特性(特别是在隔离性方面),但它能够保证命令的原子性。

业务亮点

  1. 原子性:Redis事务中的命令或者全部执行成功,或者全部不执行。即使有命令失败,所有操作基因都会回滚。
  2. 隔离性:但是Redis中的事务的命令是按顺序执行的,Redis不支持多事务的并发控制,事务之间是串行执行的。
  3. 持久化:Redis 的事务没有自动回滚机制,所以即使某个命令失败,Redis 仍然会把前面的命令写入数据存储。

Redis 事务的命令

  • MULTI:标志事务的开始,开启事务。
  • EXEC:执行事务中的所有命令。
  • DISCARD:放弃事务中的命令,取消事务。
  • WATCH:监视一个或多个键,当键被修改时,事务将失败。

真实案例:Redis支持事务的应用

需求场景

假设我们有一个电子商务系统,其中有一个商品库存管理功能,我们需要保证在一个事务中同时减少库存和记录订单,保证这两个操作要么同时成功,要么都失败。

场景说明:

  1. 用户购买一件商品,系统需要:
  • 减少该商品的库存数量。
  • 创建一个订单记录。
  1. 如果两次操作出现失败,我们希望回滚操作,而不改变任何数据。

代码实现

下面我们来实现一个简单的Redis事务,模拟商品库存减少和订单记录操作。

Java + Redis 事务代码实现

我们使用 Jedis(Redis 的 Java 客户端)来实现 Redis 事务。假设我们有两个 Redis key:

  • product:{productId}:stock:存储商品库存。
  • order:{orderId}:status:存储订单状态。
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;

public class RedisTransactionExample {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost", 6379);

        String productId = "12345";
        String orderId = "order123";
        
        try {
            // 开始 Redis 事务,首先监视库存和订单
            jedis.watch("product:" + productId + ":stock", "order:" + orderId + ":status");

            // 获取商品库存
            String stockStr = jedis.get("product:" + productId + ":stock");
            int stock = Integer.parseInt(stockStr);

            if (stock > 0) {
                // 启动事务
                Transaction transaction = jedis.multi();

                // 执行事务中的命令:减少库存
                transaction.decrBy("product:" + productId + ":stock", 1);
                
                // 执行事务中的命令:创建订单记录
                transaction.set("order:" + orderId + ":status", "created");

                // 提交事务
                java.util.List<Object> results = transaction.exec();
                
                if (results == null || results.isEmpty()) {
                    System.out.println("事务失败,某些 key 被修改,事务已回滚!");
                } else {
                    System.out.println("事务执行成功,库存减少,订单已创建!");
                }
            } else {
                System.out.println("库存不足,无法创建订单!");
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("发生错误,事务失败!");
        } finally {
            jedis.close();
        }
    }
}

解释:

  1. watch命令:首先我们使用jedis.watch()监视商品库存和订单状态。如果在执行事务之前这两个值发生了变化事务,事务将会失败。
  2. 多命令:调用multi()开启一个事务。此后的所有命令会被排序,而不会立即执行。
  3. 命令执行:在事务中,我们使用decrBy命令减少库存,使用set命令创建订单。
  4. exec命令:通过exec()提交事务。如果执行过程中某个键被改变(例如库存被其他用户修改),事务将失败。

事务的规划和优化

尽管Redis提供了事务支持,但它的事务机制并不完善,存在一些局限性:

  1. 不具备隔离性:Redis 事务中的命令是按顺序执行的,但它们不具备数据库级的隔离性。
  2. 没有回滚机制:如果在事务中某个命令失败,Redis 不会自动回滚之前的命令。我们需要手动处理错误,确保数据一致性。
  3. 不支持复杂的事务逻辑:对于需要多个表之间复杂操作的事务,Redis 并不适合。

资料里没有你的场景?

把你手上的数据和想解决的那个环节发上来,我们按具体情况回,不复述方法论。

发布需求