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


前言

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


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

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

1.1 使用 Redisson 实现 Session 共享

实现原理:
将会话内容存储在RedisHash 结构中,利用 Redisson 的分布式对象管理 API 实现透明化存取。
Maven 依赖:


<dependency>

<groupId>org.redisson
</groupId>

<artifactId>redisson-spring-boot-starter
</artifactId>

<version>3.23.2
</version>

</dependency>

配置 Redisson 客户端:

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

会话管理服务:

@Service public class SessionService { @Autowired private RedissonClientredissonClient; // 存储会话数据 public void putSession(StringsessionId, 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(StringsessionId, String key) { RMap< String , Object>sessionMap=redissonClient.getMap("session:" +sessionId) ; returnsessionMap.get(key) ; } // 销毁会话 public void invalidateSession(StringsessionId) {redissonClient.getMap("session:" +sessionId).delete( ) ; } }

Controller 中应用示例:

@RestController public class AuthController { @Autowired private SessionServicesessionService; @PostMapping ("/login" ) public String login(@RequestBody User user, HttpServletRequestrequest) { // 验证用户逻辑... StringsessionId=request.getSession( ).getId( ) ;sessionService.putSession(sessionId, "user" , user) ; return "Login success! Session: " +sessionId; } @GetMapping ("/profile" ) public User profile(HttpServletRequestrequest) { StringsessionId=request.getSession( ).getId( ) ; return (User )sessionService.getSession(sessionId, "user" ) ; } }

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

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

2.1 RDelayedQueue 核心机制

RDelayedQueue 核心机制

2.2 订单超时处理实战

订单服务实现:

@Service public class OrderService { @Autowired private RedissonClientredissonClient; // 创建订单并加入延迟队列 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 { StringorderId=blockingQueue.take( ) ; // 阻塞获取到期订单 handleExpiredOrder(orderId) ; } catch (InterruptedException e) { Thread.currentThread( ).interrupt( ) ; break ; } } } ).start( ) ; } // 处理过期订单 private void handleExpiredOrder(StringorderId) { 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) ; // 释放库存等后续操作... } } }

支付回调逻辑:

public void onPaymentSuccess(StringorderId) { // 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 调用。这两个方案可扩展到更多场景:

  • 会话管理 → 分布式权限系统
  • 延迟队列 → 定时通知、预约体系
posted on 2025-07-14 22:39  ljbguanli  阅读(23)  评论(0)    收藏  举报