受到博客:https://www.cnblogs.com/nullcc/p/5924244.html 的启发,本人对旧平台进行改造,使用redis来对任务task进行缓存,确保task的持久化,防止宕机等情况造成的损失。
旧平台采用负载均衡打分机制,taskmanager(调度管理系统)将所有task分发到activemq中,由activemq进行存储。而新平台因结构的变化,taskmanager需要自己存储task,因此新建一个task缓存池来进行存储。
一、redis存储结构
redis中设立五个list,分别为taskPool:9,taskPool:6,taskPool:4,taskPool:2,taskPool:0
分别对应着任务的五个优先级(9,6,4,2,0),取的顺序是先取优先级最高的taskPool:9,如果为空再考虑taskPool:6,以此类推。
二、编写java代码实现存取
核心点:
- queueSizeMap对每个队列的长度进行记录,当队列为空时直接跳过不进行访问,这样能大幅提高获取效率(因为与redis建立连接获取数据耗时相对较长)
- poolSize 记录缓存池总长度,如果为空便进入阻塞。
/**
*
*/
package com.YYSchedule.task.queue;
/**
* @author ybt
*
* @date 2019年2月7日
* @version 1.0
*/
@Component
@Scope("singleton")
public class PriorityTaskPool
{
private static final Logger LOGGER = LoggerFactory.getLogger(PriorityTaskPool.class);
private static final int[] nums = {9,6,4,2,0};
//记录池中任务总数量
private AtomicInteger poolSize = new AtomicInteger(0);
//记录池中每个优先级队列的容量
private Map<Integer,AtomicInteger> queueSizeMap = new ConcurrentHashMap<>();
@Autowired
@Qualifier("jedisTemplate")
public RedisTemplate<String,String> redisTemplate;
//初始化 poolSize和queueSizeMap
@PostConstruct
public void init() {
for(int i = 0; i < nums.length; i++)
{
int size = RedisUtils.size(redisTemplate, "taskPool:"+nums[i]);
queueSizeMap.put(nums[i], new AtomicInteger(size));
poolSize.addAndGet(size);
}
}
public boolean add(Task task)
{
String taskJson = JSONObject.toJSONString(task);
if(RedisUtils.set(redisTemplate, "taskPool:" + task.getTaskPriority(), taskJson))
{
queueSizeMap.get(task.getTaskPriority()).incrementAndGet();
poolSize.incrementAndGet();
return true;
}
return false;
}
public int add(List<Task> taskList)
{
int ret = 0;
for (Task task : taskList)
{
String taskJson = JSONObject.toJSONString(task);
if(RedisUtils.set(redisTemplate, "taskPool:" + task.getTaskPriority(), taskJson))
{
ret++;
queueSizeMap.get(task.getTaskPriority()).incrementAndGet();
}
}
poolSize.addAndGet(ret);
return ret;
}
/**
* 从池中获取一个task
* @return
*/
public synchronized Task get()
{
for(int i = 0; i < nums.length; i++)
{
if(queueSizeMap.get(nums[i]).get() > 0)
{
String taskJson = RedisUtils.get(redisTemplate, "taskPool:" + nums[i]);
Task task = JSONObject.parseObject(taskJson,Task.class);
queueSizeMap.get(nums[i]).decrementAndGet();
poolSize.decrementAndGet();
return task;
}
}
return null;
}
/**
* 获取制定数量的task,如果池中数量少于num,则全部给出。
* @param num
* @return
*/
public synchronized List<Task> get(int num)
{
List<Task> list = new ArrayList<>();
for(int i = 0; i < nums.length; i++)
{
AtomicInteger atomicInteger = queueSizeMap.get(nums[i]);
while(atomicInteger.get() > 0)
{
String taskJson = RedisUtils.get(redisTemplate, "taskPool:" + nums[i]);
Task task = JSONObject.parseObject(taskJson,Task.class);
atomicInteger.decrementAndGet();
list.add(task);
if(list.size() == num)
break;
}
}
poolSize.getAndSet(poolSize.get() - list.size());
return list;
}
}