依星源码资源网,依星资源网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

【好消息,好消息,好消息】VIP会员可以发表文章赚积分啦 !
查看: 101|回复: 0

基于Redission实现分布式调度任务选主

[复制链接] 主动推送

1万

主题

1万

帖子

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
15435
发表于 2025-4-15 11:48:31 | 显示全部楼层 |阅读模式
基于Redission实现分布式调度任务选主
在Spring Cloud微服务架构中,基于Redisson实现分布式调度任务的选主和心跳监听,可以通过以下完整方案实现。该方案结合了Redisson的分布式锁和发布/订阅功能,确保高可靠性和实时性:
一、整体架构设计

基于Redission实现分布式调度任务选主

基于Redission实现分布式调度任务选主

二、核心实现步骤1. 添加依赖
  1. <!-- Redisson Starter -->
  2. <dependency>
  3.     <groupId>org.redisson</groupId>
  4.     <artifactId>redisson-spring-boot-starter</artifactId>
  5.     <version>3.23.2</version>
  6. </dependency>
复制代码
2. 选主服务实现
  1. import org.redisson.api.RLock;
  2. import org.redisson.api.RedissonClient;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.stereotype.Service;

  5. import javax.annotation.PostConstruct;
  6. import javax.annotation.PreDestroy;
  7. import java.util.concurrent.TimeUnit;

  8. @Service
  9. public class LeaderElectionService {

  10.     private static final String LEADER_LOCK_KEY = "scheduler:leader:lock";
  11.     private static final String HEARTBEAT_CHANNEL = "scheduler:heartbeat";

  12.     @Autowired
  13.     private RedissonClient redisson;
  14.    
  15.     private volatile boolean isLeader = false;
  16.     private RLock leaderLock;
  17.     private Thread heartbeatThread;

  18.     @PostConstruct
  19.     public void init() {
  20.         leaderLock = redisson.getLock(LEADER_LOCK_KEY);
  21.         startElection();
  22.         startHeartbeatListener();
  23.     }

  24.     private void startElection() {
  25.         // 尝试获取领导权(非阻塞式)
  26.         new Thread(() -> {
  27.             while (!Thread.currentThread().isInterrupted()) {
  28.                 try {
  29.                     // 尝试获取锁,锁过期时间30秒
  30.                     boolean acquired = leaderLock.tryLock(0, 30, TimeUnit.SECONDS);
  31.                     if (acquired) {
  32.                         isLeader = true;
  33.                         System.out.println("当前节点当选为Leader");
  34.                         startHeartbeatTask(); // 启动心跳任务
  35.                         break;
  36.                     }
  37.                     Thread.sleep(5000); // 每5秒重试一次
  38.                 } catch (InterruptedException e) {
  39.                     Thread.currentThread().interrupt();
  40.                 }
  41.             }
  42.         }).start();
  43.     }

  44.     private void startHeartbeatTask() {
  45.         heartbeatThread = new Thread(() -> {
  46.             while (isLeader && !Thread.currentThread().isInterrupted()) {
  47.                 try {
  48.                     // 1. 续期锁(看门狗机制会自动处理)
  49.                     // 2. 发布心跳
  50.                     redisson.getTopic(HEARTBEAT_CHANNEL)
  51.                            .publish(System.currentTimeMillis());
  52.                     
  53.                     Thread.sleep(10000); // 每10秒发送一次心跳
  54.                 } catch (InterruptedException e) {
  55.                     Thread.currentThread().interrupt();
  56.                 }
  57.             }
  58.         });
  59.         heartbeatThread.start();
  60.     }

  61.     private void startHeartbeatListener() {
  62.         // 监听Leader心跳
  63.         redisson.getTopic(HEARTBEAT_CHANNEL)
  64.                .addListener(Long.class, (channel, heartbeatTime) -> {
  65.                    System.out.println("收到Leader心跳: " + heartbeatTime);
  66.                    // 可在此更新最后一次心跳时间
  67.                });
  68.     }

  69.     @PreDestroy
  70.     public void shutdown() {
  71.         if (isLeader && leaderLock.isHeldByCurrentThread()) {
  72.             leaderLock.unlock();
  73.             isLeader = false;
  74.             if (heartbeatThread != null) {
  75.                 heartbeatThread.interrupt();
  76.             }
  77.         }
  78.     }

  79.     public boolean isLeader() {
  80.         return isLeader;
  81.     }
  82. }
复制代码
3. 健康检查增强
  1. @Service
  2. public class HealthCheckService {
  3.    
  4.     @Autowired
  5.     private RedissonClient redisson;
  6.    
  7.     private volatile long lastHeartbeatTime = 0;
  8.    
  9.     @PostConstruct
  10.     public void init() {
  11.         // 定时检查Leader状态
  12.         Executors.newSingleThreadScheduledExecutor()
  13.                 .scheduleAtFixedRate(this::checkLeaderStatus, 0, 5, TimeUnit.SECONDS);
  14.     }
  15.    
  16.     private void checkLeaderStatus() {
  17.         Long currentTime = redisson.getBucket("scheduler:leader:heartbeat").get();
  18.         if (currentTime != null) {
  19.             lastHeartbeatTime = currentTime;
  20.         }
  21.         
  22.         // 超过30秒未收到心跳认为Leader失效
  23.         if (System.currentTimeMillis() - lastHeartbeatTime > 30000) {
  24.             System.out.println("Leader可能已宕机,触发重新选举");
  25.             // 可在此触发主动抢锁逻辑
  26.         }
  27.     }
  28. }
复制代码
三、关键优化点1. 多级故障检测[td]
检测方式触发条件恢复动作
Redisson看门狗超时锁续期失败(默认30秒)自动释放锁,其他节点可竞争
主动心跳超时自定义阈值(如30秒)强制释放锁并重新选举
Redis连接断开ConnectionState.LOST暂停选举直到连接恢复

2. 选举性能优化配置
  1. # application.yml
  2. redisson:
  3.   lock:
  4.     watchdog-timeout: 30000 # 看门狗超时时间(ms)
  5.   threads: 16 # 事件处理线程数
  6.   netty-threads: 32 # Netty工作线程数
复制代码
3. 脑裂防护方案
  1. // 使用Redisson的MultiLock实现多Redis节点锁
  2. RLock lock1 = redissonClient1.getLock(LEADER_LOCK_KEY);
  3. RLock lock2 = redissonClient2.getLock(LEADER_LOCK_KEY);
  4. RLock multiLock = redisson.getMultiLock(lock1, lock2);

  5. boolean acquired = multiLock.tryLock(0, 30, TimeUnit.SECONDS);
复制代码
四、生产环境部署建议1. Redis架构选择[td]
部署模式适用场景建议配置
哨兵模式高可用要求高3哨兵+3Redis实例
Cluster模式大数据量+高性能至少6节点(3主3从)
单节点仅开发测试不推荐生产使用

2. 监控指标
  1. // 暴露Redisson指标(配合Spring Boot Actuator)
  2. @Bean
  3. public RedissonMetricsBinder redissonMetrics(RedissonClient redisson) {
  4.     return new RedissonMetricsBinder(redisson);
  5. }
复制代码
监控关键指标:
  • redisson.executor.active_threads:活跃线程数
  • redisson.pubsub.subscriptions:订阅数量
  • redisson.connections.active:活跃连接数
3. 灾备方案
  • 双活数据中心:通过RedissonClient配置多区域端点
    1. Config config = new Config();
    2. config.useClusterServers()
    3.     .addNodeAddress("redis://dc1-node1:6379")
    4.     .addNodeAddress("redis://dc2-node1:6379");
    复制代码

  • 降级策略:本地缓存最后已知状态
    1. @Bean
    2. @Primary
    3. public LeaderService fallbackLeaderService() {
    4.     return new FallbackLeaderService(redisLeaderService, localCache);
    5. }
    复制代码

五、与Spring Cloud集成1. 调度任务控制
  1. @Scheduled(fixedRate = 5000)
  2. public void scheduledTask() {
  3.     if (leaderElectionService.isLeader()) {
  4.         // 只有Leader执行的逻辑
  5.         processBatchData();
  6.     }
  7. }
复制代码
2. 动态配置更新
  1. @RefreshScope
  2. @RestController
  3. @RequestMapping("/leader")
  4. public class LeaderController {
  5.    
  6.     @Value("${election.timeout:30000}")
  7.     private long electionTimeout;
  8.    
  9.     @Autowired
  10.     private LeaderElectionService electionService;
  11.    
  12.     @PostMapping("/timeout")
  13.     public void updateTimeout(@RequestParam long timeout) {
  14.         // 动态调整选举超时
  15.         electionService.setElectionTimeout(timeout);
  16.     }
  17. }
复制代码
六、方案优势总结
  • 亚秒级故障检测:通过Redis Pub/Sub实现实时通知
  • 自动故障转移:Redisson看门狗机制保障锁释放
  • 弹性扩展:支持动态增减微服务实例
  • 最小依赖:仅需Redis集群,无需额外组件
  • 与Spring生态无缝集成:完美配合@Scheduled等组件







相关帖子

扫码关注微信公众号,及时获取最新资源信息!下载附件优惠VIP会员6折;永久VIP4折
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

免责声明:
1、本站提供的所有资源仅供参考学习使用,版权归原著所有,禁止下载本站资源参与商业和非法行为,请在24小时之内自行删除!
2、本站所有内容均由互联网收集整理、网友上传,并且以计算机技术研究交流为目的,仅供大家参考、学习,请勿任何商业目的与商业用途。
3、若您需要商业运营或用于其他商业活动,请您购买正版授权并合法使用。
4、论坛的所有内容都不保证其准确性,完整性,有效性,由于源码具有复制性,一经售出,概不退换。阅读本站内容因误导等因素而造成的损失本站不承担连带责任。
5、用户使用本网站必须遵守适用的法律法规,对于用户违法使用本站非法运营而引起的一切责任,由用户自行承担
6、本站所有资源来自互联网转载,版权归原著所有,用户访问和使用本站的条件是必须接受本站“免责声明”,如果不遵守,请勿访问或使用本网站
7、本站使用者因为违反本声明的规定而触犯中华人民共和国法律的,一切后果自己负责,本站不承担任何责任。
8、凡以任何方式登陆本网站或直接、间接使用本网站资料者,视为自愿接受本网站声明的约束。
9、本站以《2013 中华人民共和国计算机软件保护条例》第二章 “软件著作权” 第十七条为原则:为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬。若有学员需要商用本站资源,请务必联系版权方购买正版授权!
10、本网站如无意中侵犯了某个企业或个人的知识产权,请来信【站长信箱312337667@qq.com】告之,本站将立即删除。
郑重声明:
本站所有资源仅供用户本地电脑学习源代码的内含设计思想和原理,禁止任何其他用途!
本站所有资源、教程来自互联网转载,仅供学习交流,不得商业运营资源,不确保资源完整性,图片和资源仅供参考,不提供任何技术服务。
本站资源仅供本地编辑研究学习参考,禁止未经资源商正版授权参与任何商业行为,违法行为!如需商业请购买各资源商正版授权
本站仅收集资源,提供用户自学研究使用,本站不存在私自接受协助用户架设游戏或资源,非法运营资源行为。
 
在线客服
点击这里给我发消息 点击这里给我发消息 点击这里给我发消息
售前咨询热线
312337667

微信扫一扫,私享最新原创实用干货

QQ|免责声明|小黑屋|依星资源网 ( 鲁ICP备2021043233号-3 )|网站地图

GMT+8, 2025-4-30 10:42

Powered by Net188.com X3.4

邮箱:312337667@qq.com 客服QQ:312337667(工作时间:9:00~21:00)

快速回复 返回顶部 返回列表