Redisson实现 如果一个外卖配送单子要发布,现在有200个骑手都想要接这一单,如何保证只有一个骑手接到单子?

Redisson实现

要实现只有一个骑手接到外卖配送单子,可以使用分布式锁来确保只有一个骑手能够成功接单。下面是一种基于Java和Spring Boot的实现方式:

  1. 引入依赖:在项目的pom.xml文件中添加以下依赖,用于使用分布式锁的功能。这是一个示例,你可以根据具体需求选择适合的分布式锁库。
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.16.2</version>
</dependency>
  1. 配置Redisson:在Spring Boot的配置文件中添加Redisson的配置,用于连接Redis服务。
spring:
  redis:
    host: your-redis-host
    port: your-redis-port
  1. 创建接单服务:创建一个接单服务类,使用分布式锁来保证只有一个骑手能够成功接单。
package com.tan.springboot2.p1;

import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class OrderService {

    private static final String LOCK_KEY = "order-lock:";

    @Autowired
    private RedissonClient redissonClient;

    public boolean takeOrder(Integer orderId) {
        RLock lock = redissonClient.getLock(LOCK_KEY + orderId);
        try {
            // 尝试获取分布式锁,设置锁的过期时间,避免锁长时间占用
            boolean locked = lock.tryLock(10, 300, TimeUnit.SECONDS);
            if (locked) {
                log.info("cg");
                // 在这里实现接单逻辑
                Thread.sleep(280 * 1000L);
                // ...
                return true; // 接单成功
            } else {
                log.info("sb");
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock(); // 释放锁
            }
        }
        return false; // 接单失败
    }
}


package com.tan.springboot2.p1;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

//(160条消息) 如果一个外卖配送单子要发布,现在有200个骑手都想要接这一单,如何保证只有一个骑手接到单子?_powerTan01的博客-CSDN博客
//https://blog.csdn.net/tanwu1/article/details/130721622

@RestController
@RequestMapping("/p1")
public class P {

    @Autowired
    OrderService orderService;

    @GetMapping("/m/{orderId}")
    public boolean m(@PathVariable Integer orderId) {
        return orderService.takeOrder(orderId);
    }

}


在上述代码中,通过RedissonClient获取一个分布式锁实例,并使用tryLock方法尝试获取锁。如果成功获取到锁,则执行接单逻辑,完成后释放锁。如果无法获取到锁,表示已经有其他骑手接单,返回接单失败。

这样,当有多个骑手同时调用takeOrder方法时,只有一个骑手能够成功获取到分布式锁并接单,其他骑手将无法获取到锁,从而实现了只有一个骑手能够接到单子的效果。

请注意,在使用分布式锁时,需要确保Redis服务正常运行,并且配置的锁过期时间合理,以避免锁长时间占用。此外,还需处理可能的异常情况,例如锁获取超时或中断等。

以上是一个基于Java和Spring Boot的实现示例,具体实现方式可能会根据实际需求和项目架构有所不同。

在这里插入图片描述

boolean locked = lock.tryLock(10, 300, TimeUnit.SECONDS); 锁续期规则是怎么样

在Redisson中,使用tryLock方法获取分布式锁时,可以指定一个锁续期的时间。当成功获取到锁时,会为该锁设置一个过期时间,并在到期前不断自动进行续期。

锁续期规则如下:

  • 初始获取锁时,设置的过期时间即为锁的初始过期时间。
  • 在获取锁成功后,Redisson会在锁的过期时间的2/3处开始自动进行续期。
  • 续期的时间间隔是通过心跳机制来控制的,每隔一定的时间,Redisson会向Redis发送续期指令,更新锁的过期时间。

具体的续期机制可以保证在获取锁成功后,只要锁的持有者仍在运行,并且没有发生异常情况,锁会一直持有,直到锁的持有者释放锁或发生锁超时。

tryLock方法中,你可以传入等待时间参数,用于等待获取锁的最大时间。如果在等待时间内无法获取到锁,tryLock方法会返回false,表示获取锁失败。

需要注意的是,锁的续期是在Redisson客户端自动进行的,而不是在Redis服务器端。因此,如果Redisson客户端发生意外终止或网络故障,可能导致锁无法进行续期,最终导致锁的过期。

综上所述,通过合理设置锁的过期时间和等待时间,可以在分布式环境中实现可靠的锁续期机制。但仍需注意处理可能的异常情况和故障恢复策略,以确保锁的正常使用。

org.redisson.api.RLock#tryLock 不会锁续期 对吗,怎么锁续期

org.redisson.api.RLock#tryLock 方法是 Redisson 分布式锁中的一种尝试获取锁的方式。这个方法是非阻塞的,它会尝试获取锁,如果成功获取到锁,则返回 true,否则返回 false。关于锁的续期,Redisson 在锁的基础上提供了自动续期的机制。

在 Redisson 中,一旦通过 RLock 获取到锁,就会启动一个续期任务,定期地给锁进行续期,防止锁的持有者因为各种原因导致锁过期而被释放。默认情况下,锁的续期时间是30秒,如果在这个时间内锁的持有者一直在持有锁,那么锁会被自动续期,避免因为锁过期而导致其他线程获取到锁。

如果你想要手动调整续期时间,可以使用 org.redisson.api.RLock#lock(long leaseTime, TimeUnit unit) 方法,其中 leaseTime 参数表示锁的持有时间,unit 参数表示时间单位。通过这个方法可以手动设置锁的持有时间,超过指定时间后锁会自动释放。

示例代码:

RLock lock = redisson.getLock("myLock");
try {
    boolean isLocked = lock.tryLock(10, TimeUnit.SECONDS); // 尝试获取锁,最多等待10秒
    if (isLocked) {
        // 成功获取到锁,执行业务逻辑
        // ...

        // 手动续期,设置锁的持有时间为60秒
        lock.lock(60, TimeUnit.SECONDS);
    } else {
        // 未能获取到锁,处理获取失败的逻辑
        // ...
    }
} finally {
    // 释放锁
    lock.unlock();
}

在上述代码中,lock(60, TimeUnit.SECONDS) 表示手动设置锁的持有时间为60秒,即在获取锁成功后,60秒内一直持有锁,并且在这60秒内定期续期,避免因为锁过期而被释放。

代码

https://github.com/tanwu001/springboot2.1
p1包中

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值