参考:https://news.sohu.com/a/566698836_121124376

背景:为了更快的响应客户端的请求,针对大量的记录需要入库(插入数据库),通过MQ实现异步入库。

注意:MQ是异步的,有可能还发生重试, 所以需要做好重复消费的问题。也需要做好插入数据失败后,重写的问题。

        

 

    /**
    * @desc   : 异步入库
    **/
    private void asyncInsertToDb(){
       // 准备好插入的对象
        ActivityPlayerTaskDO playerTaskDO = new ActivityPlayerTaskDO();

      // MQ的传输对象,指定哪个接口的哪个方法 执行插入操作(含参数)。
        Map<String,Object> map = new HashMap<>();
        map.put("BeanName", SpringContextUtil.getBeanName(IActivityPlayerTaskService.class));
        map.put("BeanMethod", "savePlayerTask");
        Object[] params = new Object[1];
        params[0] = playerTaskDO;
        map.put("params", params);

// 写到MQ中
        rabbitTemplate.convertAndSend(RabbitMqTaskConfig.PLATFORM_GAME_TASK_DIRECT_EXCHANGE,
              RabbitMqTaskConfig.PLATFORM_GAME_TASK_ASYNC_WRITE_DB_QUEUE_KEY, map);
    }

 

MQ接收到请求后的处理:

    /**
    * @desc   : 异步执行sql,写数据库
    **/
    @Override
    public Boolean asyncWriteDb(Map<String, Object> mqParam){
        Object beanName = mqParam.get("BeanName");
        if(beanName == null){
            return Boolean.FALSE;
        }
        Object beanMethod = mqParam.get("BeanMethod");
        if(beanMethod == null){
            return Boolean.FALSE;
        }

        Object params = mqParam.get("params");
        if(params == null || !(params instanceof Object[])){
            return Boolean.FALSE;
        }


        Object service = SpringContextUtil.getBean((String)beanName);
        Object[] paramArray = (Object[])params;
        Class<? extends Object>[] paramClass = new Class[paramArray.length];
        for (int i = 0; i < paramArray.length; i++) {
            if(paramArray[i] instanceof List){
                paramClass[i] = List.class;
            }else {
                paramClass[i] = paramArray[i].getClass();
            }
        }

        // 找到方法
        Method method = ReflectionUtils.findMethod(service.getClass(), (String)beanMethod,paramClass);
        // 根据 服务名称 ,方法名 反射调用
        Object result =  ReflectionUtils.invokeMethod(method, service, paramArray);
        if(result instanceof Boolean){
            //失败后,写延迟队列,一分钟后重试,MQ
            Boolean bool = (Boolean)result;
            if(!bool) {
                log.error("异步写数据库,失败了,写延迟队列(通过延迟队列实现失败后的重写),service.getClass={},beanMethod={}",service.getClass(),beanMethod);
                rabbitTemplate.convertAndSend(RabbitMqTaskConfig.PLATFORM_GAME_TASK_DELAY_EXCHANGE,
                        RabbitMqTaskConfig.PLATFORM_GAME_TASK_ASYNC_WRITE_DB_DELAY_QUEUE_KEY, mqParam, message -> {
                    message.getMessageProperties().setHeader("x-delay", 60000);
                    return message;
                });
            }
            return bool;
        }

        return Boolean.FALSE;
    }

 

posted on 2023-02-23 14:30  毛会懂  阅读(162)  评论(0编辑  收藏  举报