在ACK重发哪里有疑问

来源:7-26 IM服务中的消息ACK确认机制(下)

qianlan02

2024-12-28

// 为-1时说明已经被清除了。也就是正确收到了
if (retryTimes < 0) {
    return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
//只支持一次重发
if (retryTimes < 2) {
    msgAckCheckService.recordMsgAck(imMsgBody, retryTimes + 1);
    msgAckCheckService.sendDelayMsg(imMsgBody);
    routerHandlerService.sendMsgToClient(imMsgBody);
} else { 
    msgAckCheckService.doMsgAck(imMsgBody);
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;

为什么重发次数大于等于2的时候我们直接将记录删除,并最终返回了成功?如果没有收到ACK确认的话并不能认为一定成功吧

写回答

1回答

Danny_Idea

2024-12-29

if (retryTimes < 2) {
    msgAckCheckService.recordMsgAck(imMsgBody, retryTimes + 1);
    msgAckCheckService.sendDelayMsg(imMsgBody);
    routerHandlerService.sendMsgToClient(imMsgBody);
} else { 
  
    msgAckCheckService.doMsgAck(imMsgBody);
}

这里的doMsgAck可能是函数命名的问题容易让人理解有所歧义,它底层的代码如下:

public void doMsgAck(ImMsgBody imMsgBody) {
    String key = cacheKeyBuilder.buildImAckMapKey(imMsgBody.getUserId(), imMsgBody.getAppId());
    redisTemplate.opsForHash().delete(key, imMsgBody.getMsgId());
    redisTemplate.expire(key,30, TimeUnit.MINUTES);
}

这段代码主要是将之前redis中的记录给删除,避免说如果大量离线用户无法接收消息,则会有大量无用缓存占用redis内存的问题。

其实经过之前一定次数的重试(每次重试都有一定的时间间隔),多次都未能成功,则很可能用户已经是和IM产生断联行为了,再做过多重试的话,意义并不高,因此此时选择放弃重试会更合理一些(删除缓存)。



0
1
qianlan02
懂了
2024-12-30
共1条回复

SpringCloudAlibaba高并发仿斗鱼直播平台实战

SpringCloudAlibaba高并发仿斗鱼直播平台实战

421 学习 · 344 问题

查看课程