新任务管理系统YYSchedule-细节-使用redis实现任务缓存池(多优先级队列)

受到博客: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代码实现存取

核心点:

  1. queueSizeMap对每个队列的长度进行记录,当队列为空时直接跳过不进行访问,这样能大幅提高获取效率(因为与redis建立连接获取数据耗时相对较长)
  2. 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;
	}
	
}

猜你喜欢

转载自blog.csdn.net/bintoYu/article/details/86770941