基于redis实现异步消息队列

@Configuration
public class ThreadPoolConfig {

    /**
     * 事件处理线程池
     *
     * @return Executor
     */
    @Bean(name = "eventThreadPool")
    public ThreadPoolTaskExecutor eventThreadPool() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //核心线程数目
        executor.setCorePoolSize(8);
        //指定最大线程数
        executor.setMaxPoolSize(10);
        //队列中最大的数目
        executor.setQueueCapacity(1500);
        //线程名称前缀
        executor.setThreadNamePrefix("eventThreadPool_");
        //rejection-policy:当pool已经达到max size的时候,如何处理新任务
        //CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行
        //对拒绝task的处理策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //线程空闲后的最大存活时间
        executor.setKeepAliveSeconds(60);
        //加载
        executor.initialize();
        return executor;
    }
}
/**
 * 事件队列消费者
 */
@Component
public class EventQueueConsumer implements InitializingBean, ApplicationContextAware {
    @Autowired
    StringRedisTemplate redisTemplate;

    @Resource(name = "eventThreadPool")
    ThreadPoolTaskExecutor eventThreadPool;

    // 用来寻找Handler
    private ApplicationContext applicationContext;

    private final static Logger LOGGER = LoggerFactory.getLogger(EventQueueConsumer.class);

    // 注册事件与Handler映射
    // (一个事件类型可以对应多个handler处理,目前一个事件类型对应一个handler处理器)
    private Map<String, List<EventHandler>> eventConfig = new HashMap<>();

    // 注册Handler到相应的事件
    @Override
    public void afterPropertiesSet() throws Exception {
        Map<String, EventHandler> handlerBeans = applicationContext.getBeansOfType(EventHandler.class);
        if(handlerBeans != null){
            // 依次遍历每个找到的Handler(被@Component注解标注的)
            for (Map.Entry<String, EventHandler> entry : handlerBeans.entrySet()) {
                // 获取每个Handler支持的事件eventType
                String eventType = entry.getValue().getSupportedEvents();
                    if(!eventConfig.containsKey(eventType)){
                        eventConfig.put(eventType, new ArrayList<EventHandler>());
                    }
                    eventConfig.get(eventType).add(entry.getValue());
            }
        }

        new Thread(()->{
           while (true){
               String jsonStr = redisTemplate.opsForList().rightPop(RedisKeys.TOPIC_EVENTQUEUE, 1, TimeUnit.SECONDS);
               LOGGER.info("弹出元素:{}",jsonStr);
               if(StringUtils.isNotBlank(jsonStr)){
                   eventThreadPool.submit(()->{
                       EventModel eventModel = JSON.parseObject(jsonStr, EventModel.class);
                       LOGGER.info("处理任务:{}", eventModel);
                       if(eventConfig.containsKey(eventModel.getEventType())) {
                           for (EventHandler eventHandler : eventConfig.get(eventModel.getEventType())){
                               // 执行注册到该事件的每一个Handler
                               eventHandler.doHandle(eventModel);
                           }
                       }
                   });
               }
           }
        }).start();

    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

/**
 * 事件处理接口
 */
public interface EventHandler {
    // 各个具体Handler处理事件过程
    void doHandle(EventModel eventModel);

    //获取事件类型
    String getSupportedEvents();
}
/**
 * 用户分享事件处理器
 */
@Component
public class UserShareHandler implements EventHandler {

    public static final HashMap<String,Integer> EVENT_MAP = new HashMap<>();

    static{
        EVENT_MAP.put(EventType.USER_SHARE,2);
        EVENT_MAP.put(EventType.MERCHANT_SHARE,2);
    }

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    UserCouponMapper userCouponMapper;
    @Autowired
    MessageMapper messageMapper;
    @Autowired
    OperateActivityMapper operateActivityMapper;

    @Override
    public void doHandle(EventModel eventModel) {

        //用户分享事件
        if(StringUtils.isNotBlank(eventModel.getEventType()) && eventModel.getEventType().equals(EventType.USER_SHARE)){
            Message message = messageMapper.selectOne(new LambdaQueryWrapper<Message>()
                    .eq(Message::getMsgNum, eventModel.getMsgNum()));
            //设置标识已消费
            message.setIsConsume(1);
            //更新消息
            messageMapper.updateById(message);
            logger.info("消费消息:{}",eventModel);

            Long userId = eventModel.getTriggerId();
            Integer event = EVENT_MAP.get(eventModel.getEventType());

            //获取活动
            Wrapper<OperateActivity> wrapper = new LambdaQueryWrapper<OperateActivity>()
                    .eq(OperateActivity::getEvent,event)
                    .eq(OperateActivity::getUserType,1)
                    .eq(OperateActivity::getType,1)
                    .gt(OperateActivity::getEndTime,System.currentTimeMillis()/1000)
                    .lt(OperateActivity::getStartTime,System.currentTimeMillis()/1000);
            List<OperateActivity> operateActivities = operateActivityMapper.selectList(wrapper);

            //根据活动发放优惠券
            for (OperateActivity operateActivity : operateActivities) {
                Long activityId = operateActivity.getId();
                BigDecimal money = operateActivity.getMoney();
                Integer number = operateActivity.getNumber();
                Long termOfValidity = operateActivity.getTermOfValidity();
                for (int i = 0; i < number; i++) {
                    UserCoupon userCoupon = new UserCoupon();
                    userCoupon.setActivityId(activityId);
                    userCoupon.setType(1);
                    userCoupon.setMoney(money);
                    userCoupon.setUserId(userId);
                    userCoupon.setStartTime(System.currentTimeMillis()/1000);
                    userCoupon.setEndTime(System.currentTimeMillis()/1000 + termOfValidity*3600);
                    userCouponMapper.insert(userCoupon);
                }
            }

        }

    }

    @Override
    public String getSupportedEvents() {
        return EventType.USER_SHARE;
    }
}

**
 * 事件模型(可使用链式编程创建)
 */
public class EventModel implements Serializable {

    /*
     * 事件类型,不同的事件类型会触发调用不同的Handler,
     * 一种事件类型可以注册多个Handler,对应于消息队列中
     * 每个事件可能触发多个Handler异步去做其他事情。
     **/
    private String eventType;
    // 触发事件用户ID
    private Long triggerId;
    // 事件影响的用户ID
    private Long receiverId;
    //消息编号
    private String msgNum;
    //过期时间
    private Long exTime;
    //消息产生时间
    private Long createTime;
    // 额外信息
    private Map<String,Object> extraInfo = new HashMap<String,Object>();

    public String getEventType() {
        return eventType;
    }

    public Long getTriggerId() {
        return triggerId;
    }

    public Long getReceiverId() {
        return receiverId;
    }

    public Map<String, Object> getExtraInfo() {
        return extraInfo;
    }

    public Long getExTime() {
        return exTime;
    }

    public String getMsgNum() {
        return msgNum;
    }

    public Long getCreateTime() {
        return createTime;
    }

    public EventModel setEventType(String eventType) {
        this.eventType = eventType;
        return this;
    }

    public EventModel setTriggerId(Long triggerId) {
        this.triggerId = triggerId;
        return this;
    }

    public EventModel setReceiverId(Long receiverId) {
        this.receiverId = receiverId;
        return this;
    }

    public EventModel setExtraInfo(Map<String, Object> extraInfo) {
        this.extraInfo = extraInfo;
        return this;
    }

    public EventModel setMsgNum(String msgNum) {
        this.msgNum = msgNum;
        return this;
    }

    public EventModel setExTime(Long exTime) {
        this.exTime = exTime;
        return this;
    }

    public EventModel setCreateTime(Long createTime) {
        this.createTime = createTime;
        return this;
    }

    @Override
    public String toString() {
        return "EventModel{" +
                "eventType='" + eventType + '\'' +
                ", triggerId=" + triggerId +
                ", receiverId=" + receiverId +
                ", msgNum='" + msgNum + '\'' +
                ", exTime=" + exTime +
                ", createTime=" + createTime +
                ", extraInfo=" + extraInfo +
                '}';
    }
}

/**
 * 事件类型
 */
public class EventType {
    //用户首次分享事件
    public static final String USER_SHARE = "USER_SHARE";
    //商家首次分享事件
    public static final String MERCHANT_SHARE = "MERCHANT_SHARE";
}

/**
 * 事件生产者(生产消息lpush进redis)
 * 可在需要的业务逻辑处注入
 */
@Component
public class EventProducer {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    MessageMapper messageMapper;

    /**
     * lpush消息事件
     * @param eventModel
     * @return
     */
    public boolean pushEvent(EventModel eventModel){
        //将消息lpush进redis
        redisTemplate.opsForList().leftPush(RedisKeys.TOPIC_EVENTQUEUE,eventModel);
        logger.debug("生产消息:{}",eventModel);
        Message message = new Message();
        BeanUtil.copyProperties(eventModel,message);
        message.setUserId(eventModel.getTriggerId());
        message.setExtraInfo(JSONUtil.toJsonStr(eventModel.getExtraInfo()));
        message.setTopic(RedisKeys.TOPIC_EVENTQUEUE);
        //数据库插入消息数据
        messageMapper.insert(message);
        return true;
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值