SpringBoot3.0.3实战:Redisson3.20.0分布式锁与限流深度配置指南
当你的电商系统在秒杀活动中突然出现超卖,或是API接口被恶意刷爆时,分布式锁和限流就是你的救命稻草。今天我们将用SpringBoot 3.0.3和Redisson 3.20.0这两个黄金组合,手把手搭建一个能抗住百万级并发的分布式系统防护网。
1. 环境准备与避坑指南
在开始编码前,我们需要先解决环境配置这个"拦路虎"。很多新手在第一步就被Maven依赖冲突绊倒,特别是SpringBoot 3.x与Redisson的版本兼容性问题。
正确依赖配置:
<dependency> <groupId>org.redisson</groupId> <artifactId>redisson-spring-boot-starter</artifactId> <version>3.20.0</version> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </exclusion> </exclusions> </dependency>注意:SpringBoot 3.x默认使用Jakarta EE 9+,而Redisson 3.20.0需要显式排除旧版web依赖
application.yml关键配置:
spring: redis: host: 127.0.0.1 port: 6379 password: yourpassword database: 0 timeout: 3000ms redisson: config: | singleServerConfig: idleConnectionTimeout: 10000 connectTimeout: 10000 timeout: 3000 retryAttempts: 3 retryInterval: 1500 subscriptionsPerConnection: 5 connectionMinimumIdleSize: 10 connectionPoolSize: 64 dnsMonitoringInterval: 5000常见配置误区对比表:
| 错误配置 | 正确配置 | 后果差异 |
|---|---|---|
| timeout: 3 | timeout: 3000 | 前者单位不明确导致连接超时异常 |
| 不设connectionPoolSize | connectionPoolSize: 64 | 高并发时连接耗尽 |
| 单机配置集群模式 | singleServerConfig | 性能下降50%以上 |
2. 分布式锁实战:从基础到高级
2.1 基础锁实现
先看一个订单超卖防护的典型场景:
public class OrderService { @Autowired private RedissonClient redisson; public void createOrder(String productId) { RLock lock = redisson.getLock("order_lock:" + productId); try { if (lock.tryLock(5, 30, TimeUnit.SECONDS)) { // 核心业务逻辑 int stock = getStockFromDB(productId); if (stock > 0) { updateStock(productId, stock - 1); createOrderRecord(productId); } } } finally { if (lock.isLocked() && lock.isHeldByCurrentThread()) { lock.unlock(); } } } }关键点:tryLock的三个参数分别是等待时间、锁持有时间和时间单位
2.2 高级特性应用
锁续期机制:
// 自动续期配置 Config config = new Config(); config.setLockWatchdogTimeout(30000); // 默认30秒 RedissonClient redisson = Redisson.create(config); // 手动续期示例 lock.lock(10, TimeUnit.SECONDS); // 业务处理中... if(needMoreTime) { ((RedissonLock)lock).expire(30, TimeUnit.SECONDS); }不同锁类型对比:
| 锁类型 | 适用场景 | 特性 |
|---|---|---|
| RLock | 通用场景 | 可重入,支持自动续期 |
| RReadWriteLock | 读写分离 | 读锁共享,写锁排他 |
| RSemaphore | 资源池 | 控制并发访问量 |
| RFairLock | 公平竞争 | 按申请顺序获取锁 |
3. 分布式限流全方案
3.1 基础限流实现
API防护的经典配置:
public class ApiRateLimiter { private final RRateLimiter rateLimiter; public ApiRateLimiter(RedissonClient redisson, String apiKey) { this.rateLimiter = redisson.getRateLimiter("api_limit:" + apiKey); // 每秒10个令牌,桶容量20 rateLimiter.trySetRate(RateType.OVERALL, 10, 20, RateIntervalUnit.SECONDS); } public boolean allowRequest() { return rateLimiter.tryAcquire(1); } }3.2 多维度限流策略
用户级限流:
// 每个用户每分钟100次请求 rateLimiter.trySetRate(RateType.PER_CLIENT, 100, 1, RateIntervalUnit.MINUTES);滑动窗口限流:
RScoredSortedSet<String> window = redisson.getScoredSortedSet("sliding_window:" + userId); long currentTime = System.currentTimeMillis(); window.removeRangeByScore(0, true, currentTime - 60000, true); window.add(currentTime, currentTime + ""); if (window.size() > 100) { throw new RateLimitException(); }限流算法对比表:
| 算法 | 实现复杂度 | 平滑度 | 内存消耗 |
|---|---|---|---|
| 令牌桶 | 中 | 高 | 低 |
| 漏桶 | 低 | 中 | 低 |
| 滑动窗口 | 高 | 高 | 高 |
| 固定窗口 | 低 | 低 | 低 |
4. 生产环境调优指南
4.1 性能优化配置
Redisson线程池优化:
redisson: threads: 16 nettyThreads: 32 transportMode: "NIO"Redis服务器连接优化:
SingleServerConfig config = new SingleServerConfig(); config.setConnectionMinimumIdleSize(10); // 最小空闲连接 config.setConnectionPoolSize(64); // 最大连接数 config.setIdleConnectionTimeout(10000); // 空闲超时4.2 监控与故障排查
JMX监控配置:
Config config = new Config(); config.setUseScriptCache(true); config.setLockWatchdogTimeout(30000); config.setJMXEnabled(true); // 开启JMX常见问题排查清单:
- 连接超时:检查网络和timeout配置
- 锁未释放:确保finally块中释放锁
- 限流失效:检查RateType设置
- 性能瓶颈:调整连接池大小
5. 真实业务场景落地
5.1 秒杀系统实现
public class SeckillService { public boolean trySeckill(String userId, String itemId) { // 用户频控 if (!userRateLimiter.check(userId)) return false; // 商品锁 RLock lock = redisson.getLock("seckill:" + itemId); try { if (lock.tryLock(1, 10, TimeUnit.SECONDS)) { int stock = redisTemplate.opsForValue().get("stock:" + itemId); if (stock > 0) { redisTemplate.opsForValue().decrement("stock:" + itemId); createOrder(userId, itemId); return true; } } } finally { lock.unlock(); } return false; } }5.2 支付系统防重
public class PaymentService { public boolean processPayment(String paymentId) { RLock lock = redisson.getLock("payment:" + paymentId); if (!lock.tryLock()) { throw new ConcurrentPaymentException(); } try { Payment payment = paymentDao.findById(paymentId); if (payment.getStatus() != Status.NEW) { return false; } return executePayment(payment); } finally { lock.unlock(); } } }在电商系统的灰度发布中,我们曾用Redisson的分布式锁成功解决了商品库存的"超卖幽灵",那个凌晨三点发现的Bug让我深刻理解了tryLock第三个参数的重要性——它不仅是超时时间,更是系统稳定性的最后防线。