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 调用。这两个方案可扩展到更多场景:

  • 会话管理 → 分布式权限系统
  • 延迟队列 → 定时通知、预约系统
相关推荐
初次攀爬者4 天前
ZooKeeper 实现分布式锁的两种方式
分布式·后端·zookeeper
西岸行者5 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意5 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码5 天前
嵌入式学习路线
学习
毛小茛5 天前
计算机系统概论——校验码
学习
babe小鑫5 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms5 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下5 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。5 天前
2026.2.25监控学习
学习
im_AMBER5 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode