本篇旨在提供SpringCloud下多实例多库跑定时任务的优化方案
业务场景:
有这样一个需求,需要跑大数据下的定时任务,主要是查表和写表操作,量很大,要支持续跑,并且每个库的数据不一致,所以需要轮询库,假如生产有4台实例,一共有8个库,为了减小服务器的压力,并且能够同时跑8个库的任务。
需要解决几个问题:
1.确保每个库,有且只能有1个线程在跑,如果其他线程也跑了这个库,就会导致数据插入重复,浪费资源。
2.确保每个实例都能够有线程在运行定时任务,让资源充分利用。
3.如果某个任务出现问题,希望可以重跑或者有所记录。
方案一(不支持Redis集群下的解决方案):
实现细节:
1.如何轮询生产数据库?
这个就直接在配置文件配置8个库连接,然后根据你传入的库名,来实现切库操作,这个我就不贴代码了。
2.如何用Redis实现分布式锁,在网上找到一个不错的方式:
/**
* @Author: Markful
* @Description:
* 1.互斥性。在任意时刻,只有一个客户端能持有锁。
* 2.不会发生死锁。即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁。
* 3.具有容错性。只要大部分的Redis节点正常运行,客户端就可以加锁和解锁。
* 4.解铃还须系铃人。加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解了。
*
* @Version 1.0
*/
public class RedisTool {
private static final Long RELEASE_SUCCESS = 1L;
private static final String LOCK_SUCCESS = "OK";
private static final String SET_IF_NOT_EXIST = "NX";
private static final String SET_WITH_EXPIRE_TIME = "EX";
/**
* 尝试获取分布式锁
* @param jedis Redis客户端
* @param lockKey 锁
* @param requestId 请求标识
* @param expireTime 超期时间
* @return 是否获取成功
*/
public static boolean tryGetDistributedLock(Jedis jedis,String lockKey, String requestId, int expireTime){
String result = jedis.set(lockKey,requestId,SET_IF_NOT_EXIST,SET_WITH_EXPIRE_TIME,expireTime);
if(LOCK_SUCCESS.equals(re