RedissonClient-业务解决思路

该博客介绍了如何在Spring Boot应用中利用Redisson客户端进行并发控制,确保同一项目的多个负载只执行一次代码。通过创建一个临时缓存键并在缓存不存在时执行代码,同时使用Redisson的分布式锁来防止重复执行。主要涉及了Redisson的RBucket和RLock接口,以及LiveCommentStreamJob类的ApplicationRunner接口实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

如何让多个负载的项目(同一个)只执行一次代码运行

例子:

package com.ljq.service.facebook.job;

import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.redisson.client.codec.StringCodec;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.CollectionUtils;
import shop.easysell.common.lib.builder.CacheKeyBuilder;
import shop.easysell.common.lib.enumeration.CommonCacheKeyModuleEnum;
import shop.easysell.lib.facebook.domain.po.Live;
import shop.easysell.service.facebook.service.LiveService;
import shop.easysell.service.facebook.service.thirdparty.FacebookLiveService;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Configuration
@Slf4j
public class LiveCommentStreamJob implements ApplicationRunner {

    @Resource
    private LiveService liveService;
    @Resource
    private FacebookLiveService facebookLiveService;
    @Resource
    private RedissonClient redissonClient;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        String temporaryCommentStreamKey = CacheKeyBuilder.build(
                CommonCacheKeyModuleEnum.FACEBOOK,
                "live",
                "temporary",
                "commentStream",
                "job"
        );
        RBucket<String> bucket = redissonClient.getBucket(temporaryCommentStreamKey, StringCodec.INSTANCE);
        //获取缓存是否存在-存在就跳过执行
        if (!bucket.isExists()) {
            //设置数据一分钟过去
            bucket.set("running", 1, TimeUnit.MINUTES);
            //查询直播间正在直播,启动监听评论线程
            List<Live> activityLiveList = liveService.getActivityLiveList();
            if (!CollectionUtils.isEmpty(activityLiveList)) {
                activityLiveList.forEach(live -> {
                    if (log.isInfoEnabled()) {
                        log.info("直播间id:{},直播间名称:{}", live.getId(), live.getName());
                    }
                    try {
                        facebookLiveService.dealWithRealtimeComments(live);
                    } catch (Exception e) {
                        log.error("直播间id:{},直播间名称:{},处理直播评论线程异常", live.getId(), live.getName(), e);
                    }
                });
            }
        }
    }
}

加锁的使用

//加锁
String commentDealWithKey = CacheKeyBuilder.build(
        CommonCacheKeyModuleEnum.FACEBOOK,
        "live",
        "comment",
        "dealWith",
        live.getId().toString());
RLock lock = redissonClient.getLock(commentDealWithKey);
try {
    //等待3三秒,最长等待5秒
    if (lock.tryLock(3,5, TimeUnit.SECONDS)) {
        //代码内容
    }
} catch (Exception e) {
    log.error("错误日志", e);
} finally {
    if (lock.isHeldByCurrentThread()) {
        lock.unlock();
    }
}
### 分布式锁的实现方式 分布式锁是一种用于协调多个进程或服务之间访问共享资源的方式。以下是几种主流的分布式锁实现方案及其特点: #### 1. **基于 Redis 的分布式锁** Redis 是一种高性能的内存数据库,其单线程特性和原子操作使其成为实现分布式锁的理想工具。 - **核心原理**: 基于 `SETNX` (Set if Not Exists) 和 Lua 脚本实现加锁逻辑[^1]。通过设置键值对并指定过期时间来防止死锁的发生。 - **优点**: - 高性能:Redis 单线程处理请求,确保了加解锁过程中的原子性。 - 支持自动续期(看门狗机制),有效解决因程序崩溃导致的锁无法释放问题[^3]。 - **缺点**: - 如果 Redis 出现网络分区或者宕机,则可能导致锁不可用的情况发生。 - **典型库**: Redisson 提供了一套完善的 API 来简化开发人员的工作量,支持多种类型的锁(如 RedLock、RWLock 等)。它不仅实现了简单的分布式互斥锁功能,还扩展到了更复杂的场景,比如联锁和红锁[^4]。 ```java // 使用 Redisson 获取分布式锁实例 RLock lock = redissonClient.getLock("myDistributedLock"); try { boolean isLocked = lock.tryLock(10, TimeUnit.SECONDS); if (!isLocked) { throw new RuntimeException("Failed to acquire the distributed lock."); } } finally { lock.unlock(); } ``` --- #### 2. **基于 ZooKeeper 的分布式锁** ZooKeeper 是一个分布式的协作服务框架,常被用来构建可靠的分布式系统组件。 - **核心原理**: 利用临时顺序节点配合 Watcher 事件监听器完成锁定与解锁动作[^2]。客户端创建一个带有前缀路径名的小型文件夹作为候选者标志物;一旦发现当前最小编号属于己方即视为成功获取到全局唯一权限。 - **优点**: - 数据一致性强:即使部分服务器失败也不会影响整个系统的正常运转。 - 自动清理失效会话关联的数据结构,减少人为干预需求。 - **缺点**: - 复杂度较高:相较于其他轻量化存储介质而言配置较为繁琐。 - 存在网络延迟敏感性的风险,在高频次短周期任务调度环境下表现欠佳。 --- #### 3. **基于 MySQL 的分布式锁** 虽然不推荐大规模生产环境采用这种方式,但在某些特定条件下仍然可行。 - **核心思路**: 对某条记录执行更新语句的同时附加版本号校验字段约束条件达成目的[^3]。每次尝试修改之前先查询目标状态是否存在冲突情况再决定是否继续推进后续业务流程。 - **适用范围**: 主要适用于那些已经存在成熟关系型数据库基础设施却不想额外引入新依赖项的应用场合之中。 --- ### 分布式锁的使用场景 分布式锁广泛应用于各种并发控制领域,具体如下: 1. **秒杀活动库存扣减** 当大量用户同时发起购买请求时,为了避免超卖现象可以借助分布式锁串行化订单提交环节的操作序列[^1]。 2. **缓存刷新策略管理** 在多台机器共同维护一份热点数据副本的情况下,为了保证最新版能够及时同步至所有地方而不至于频繁触发不必要的 IO 开销,通常也会运用类似的手段加以保护。 3. **定时任务分配防重复执行** 不同时间段内的相同作业只允许单一实体负责实际运行工作以防出现冗余计算浪费资源的现象。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尘叶风凌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值