Redisson学习专栏(四):实战应用(分布式会话管理,延迟队列)

文章目录


前言

在现代分布式系统中,会话管理和延迟任务处理是两个核心需求。本文将深入探讨如何利用 Redisson 解决这两个问题,通过代码实战演示分布式会话共享和订单超时未支付的延迟任务处理。


一、为什么需要分布式会话管理?

在单机应用中,Session 存储在内存中。但在分布式环境下,请求可能被负载均衡到不同服务器,导致 Session 丢失。解决方案:将会话数据集中存储在 Redis 中,实现多服务共享。

1.1 使用 Redisson 实现 Session 共享

实现原理:

将会话数据存储在 Redis Hash 结构中,利用 Redisson 的分布式对象操作 API 实现透明化存取。
Maven 依赖:

xml 复制代码
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>3.23.2</version>
</dependency>

配置 Redisson 客户端:

java 复制代码
@Configuration
public class RedissonConfig {
    
    @Bean
    public RedissonClient redissonClient() {
        Config config = new Config();
        config.useSingleServer()
              .setAddress("redis://127.0.0.1:6379");
        return Redisson.create(config);
    }
}

会话管理服务:

java 复制代码
@Service
public class SessionService {

    @Autowired
    private RedissonClient redissonClient;

    // 存储会话数据
    public void putSession(String sessionId, String key, Object value) {
        RMap<String, Object> sessionMap = redissonClient.getMap("session:" + sessionId);
        sessionMap.put(key, value);
        // 设置会话过期时间(30分钟)
        sessionMap.expire(30, TimeUnit.MINUTES);
    }

    // 获取会话数据
    public Object getSession(String sessionId, String key) {
        RMap<String, Object> sessionMap = redissonClient.getMap("session:" + sessionId);
        return sessionMap.get(key);
    }

    // 销毁会话
    public void invalidateSession(String sessionId) {
        redissonClient.getMap("session:" + sessionId).delete();
    }
}

Controller 中使用示例:

java 复制代码
@RestController
public class AuthController {

    @Autowired
    private SessionService sessionService;

    @PostMapping("/login")
    public String login(@RequestBody User user, HttpServletRequest request) {
        // 验证用户逻辑...
        String sessionId = request.getSession().getId();
        sessionService.putSession(sessionId, "user", user);
        return "Login success! Session: " + sessionId;
    }

    @GetMapping("/profile")
    public User profile(HttpServletRequest request) {
        String sessionId = request.getSession().getId();
        return (User) sessionService.getSession(sessionId, "user");
    }
}

二、订单超时未支付?用延迟队列精准处理

电商场景中,订单创建后需在 30 分钟内支付,否则自动关闭。传统轮询数据库方案效率低下,Redisson 的 RDelayedQueue 是完美解决方案。

2.1 RDelayedQueue 核心机制

2.2 订单超时处理实战

订单服务实现:

java 复制代码
@Service
public class OrderService {

    @Autowired
    private RedissonClient redissonClient;
    
    // 创建订单并加入延迟队列
    public void createOrder(Order order) {
        // 1. 保存订单到数据库(状态:待支付)
        orderRepository.save(order);
        
        // 2. 加入延迟队列(30分钟超时)
        RBlockingQueue<String> blockingQueue = redissonClient.getBlockingQueue("ORDER_EXPIRE_QUEUE");
        RDelayedQueue<String> delayedQueue = redissonClient.getDelayedQueue(blockingQueue);
        delayedQueue.offer(order.getId(), 30, TimeUnit.MINUTES);
    }
    
    // 监听订单超时队列
    @PostConstruct
    public void startExpireListener() {
        new Thread(() -> {
            RBlockingQueue<String> blockingQueue = redissonClient.getBlockingQueue("ORDER_EXPIRE_QUEUE");
            while (true) {
                try {
                    String orderId = blockingQueue.take(); // 阻塞获取到期订单
                    handleExpiredOrder(orderId);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }
            }
        }).start();
    }
    
    // 处理过期订单
    private void handleExpiredOrder(String orderId) {
        Order order = orderRepository.findById(orderId).orElse(null);
        if (order != null && "UNPAID".equals(order.getStatus())) {
            order.setStatus("CANCELED");
            order.setCancelReason("支付超时");
            orderRepository.save(order);
            System.out.println("订单超时关闭: " + orderId);
            
            // 释放库存等后续操作...
        }
    }
}

支付回调逻辑:

java 复制代码
public void onPaymentSuccess(String orderId) {
    // 1. 更新订单状态为已支付
    Order order = orderRepository.findById(orderId).get();
    order.setStatus("PAID");
    orderRepository.save(order);
    
    // 2. 从延迟队列中移除(避免重复处理)
    RDelayedQueue<String> delayedQueue = redissonClient.getDelayedQueue(
        redissonClient.getBlockingQueue("ORDER_EXPIRE_QUEUE")
    );
    delayedQueue.remove(orderId); // 关键:支付成功则移除任务
}

总结

通过本文实战,我们实现了:

  1. 分布式会话管理:利用 RMap 存储会话数据,解决集群环境 Session 共享问题
  2. 精准延迟任务:基于 RDelayedQueue 实现订单超时自动关闭,替代低效轮询方案

Redisson 的强大之处在于将复杂的分布式问题抽象为简单的 API 调用。这两个方案可扩展到更多场景:

  • 会话管理 → 分布式权限系统
  • 延迟队列 → 定时通知、预约系统
相关推荐
Star(up up up)5 小时前
Redis Windows 安装教程:使用Windows 的 Redis 压缩包
redis·笔记·学习·程序人生·云原生·学习方法·改行学it
乌暮7 小时前
Spring AOP 与 Spring 事务:用大白话彻底理解原理与实践
java·数据库·spring boot·后端·sql·学习·spring
蒸蒸yyyyzwd12 小时前
从邓明学习的后端笔记
笔记·学习
机器学习之心12 小时前
基于变量相关图与残差学习的 GCN 多变量回归方法——混凝土 28 天抗压强度预测
学习·回归·gcn
kiwixing13 小时前
GaussDB|集中式还是分布式?三把尺子选型
分布式·gaussdb
真上帝的左手1 天前
30. 技术专题-‌应用框架组件-分布式架构
分布式·架构·系统架构·分布式架构
Rabitebla1 天前
【Linux】进程控制(十二) 自定义 Shell(二):内建命令与进程工作目录管理
linux·c++·笔记·学习·bash
Gary移动存储固件1 天前
eMMC5.1协议中文学习讲解(6.6.17~6.6.22.4.6)
学习·ufs·emmc·nand·存储固件
一个天蝎座 白勺 程序猿1 天前
别让收藏夹替你学习:我搭AI知识体系的完整方法,脚本直接拿去用
人工智能·学习·ai·ai学习
楚山之石1 天前
【Nat Biomed Eng】Connectome 2.0 超高梯度扫描仪:500 mT/m 与 600 T/m/s 把活体人脑微观结构分辨推进到亚微米级
图像处理·学习·数据分析·mri