问题
今天遇到一个问题,发送mq消息的时候需要保证不会重复发送,注意不是可靠到达(可靠到达可以通过消息确认机制和回调接口保证),这里保证的是不会生产多条一样的消息。
方法
综合讨论下来决定使用redis缓存来解决,因为相比于将记录插入数据库redis更为高效和便捷。
检验是否已经发送
在发送消息之前根据相关信息组合成key去redis中查找,找到后检测值是否为存在并且是否为设定的值,若存在且与设定的值一样,则返回false,说明该消息已经发送过了。
public boolean issend(string messagetype, long bizid, int hashcode) {
// 根据消息类型、业务id和哈希值组合成key
string key = this.genkey(messagetype, bizid, hashcode);
long value = super.get(key);
if (value != null && value.equals(default_value)) {
return false;
}
return true;
}
/**get方法*/
public v get(k key) {
if (key == null) {
return null;
} else {
try {
// 在key前添加前缀和名字,并将原来的key进行json序列化
string realkey = this.genrealkey(key);
string content = (string)this.redistemplate.opsforvalue().get(realkey);
// 若get到的值不为null则进行json反序列化
return content == null ? null : this.valueserializer.deserialize(content);
} catch (exception e) {
cache.error("", key.tostring(), "", "0", e);
return null;
}
}
}
以上就是检验消息是否重复的方法,需要注意的是json序列化,因为redis默认使用的是jdk序列化,这种序列化后的内容不仅多而且不易于阅读,因此将其改为json序列化。
发送后添加缓存
在发送消息的时候会先在redis中put一个以相关信息组合为key,value为默认值的记录,过期时间为5min。
public void sendmessage(string messagetype, long bizid, int hashcode) {
super.put(genkey(messagetype, bizid, hashcode), default_value);
}
/**put方法*/
public void put(k key, v value) {
try {
if (key != null && null != value) {
// 进行json序列化
string content = this.valueserializer.serialize(value);
this.redistemplate.opsforvalue().set(this.genrealkey(key), content, this.expires, this.timeunit);
}
} catch (throwable e) {
e.printstacktrace();
}
}
发送消息方法
最后的发送消息方法大致代码如下:
public void sendmqmessage(long bizid, string messagetemplatecode, string msg, int msghashcode, string exchange, string routingkey) {
//加入缓存
boolean send = true;
//string messagetype = messagetypeutil.getmessagetype(messagetemplatecode);
if (bizid != null) {
// 检测是否已经发送
send = sendmessagecache.issend(messagetemplatecode, bizid, msghashcode);
}
//发送mq消息
if (send) {
if (bizid != null) {
// 加入缓存
sendmessagecache.sendmessage(messagetemplatecode, bizid, msghashcode);
}
// 发送消息
messagesender.send(exchange, routingkey, msg);
}
}
到此这篇关于使用redis防止重复发送rabbitmq消息的方法详解的文章就介绍到这了,更多相关redis防止重复发送rabbitmq内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论