利用RocketMQ实现App消息推送系统

3,256 阅读2分钟

1.概述

分享本人设计的用于app消息模块的设计、分析、实践。

主要是利用

阿里云RocketMQ服务和Redis去实现的。用于app推送消息,和app内置消息模块红点标识。


2.数据库设计



3.业务逻辑实现图



4.实现细节分析

(1)5)需要特别注意的就是重发机制(因为无法确定第三方服务商是否宕机)

 /**
 * 重发机制伪代码
 * */
List messageList = new ArrayList();
int index = 1;
int retrySize = 5;
while (messageList.size() > 0 && index <= retrySize){
    //需要重发的数据
    List recryList = new ArrayList();
    index++;
    //调用发送
    for (int i = 0; i < messageList.size(); i++) {
        //取出消息
        Message msg = (Message)messageList.get(i);
        //发送消息
        try{
            // 同步发送消息,只要不抛异常就是成功
            SendResult sendResult = producer.send(msg);
            // 进行下一步
        }catch (Exception e){
            //将失败消息添加到重发消息内
            recryList.add(msg);
        }
    }
    //循环结束后查看是否需要重发消息
    if( recryList.size() > 0 ){
        //如果重发到第retrySize次
        if(index == retrySize){
            //直接发送报警系统
            warniingService.sendErro("重发超过retrySize");
        }
        try {
            Thread.sleep(1000 * 60 * index);    //延时 index 分钟 ,第一次1分钟, 第二次两分钟
        } catch (InterruptedException e) {
            //直接调用 系统警报系统
            warniingService.sendErro("重发sleeop报警"+e.getMessage());
        }
        //赋值重新发送消息
        messageList = recryList;

    }

}

(2)需要注意的是修改状态的时候需要加一个版本号判断,主要是防止业务系统因为机器原因导致了处理变慢,可能消息系统已经消费过了,然后导致消息重发。

update messge_inform  set messageStatus = 1 where vserion = 1

4)为了确保消息不重复消费
//实例化redis
Jedis jedis = new Jedis();

Message msg = 此处为mq消费者获取消息 ;
String msgId = msg.getMsgID();

if(jedis.exists(msgId)) {
    //存在就刷新过期时间
    jedis.expire(msgId, 1000 * 60 * 5);
}else{
    //不存在就存入id并且消费
    jedis.setex(msgId,  1000 * 60 * 5, "0");
    //消费 消息
    messageSendService.send(msg);
}