引言
订阅发布的消息模式可以表示为“发布者->事件中心<=>订阅者”的交互关系,相比于观察者模式更加灵活解耦,但相应地维护事件队列的性能消耗会变大。redisson 提供了 topic 相关功能,通过将流程拆解成向 topic 推送数据、监听 topic 消费数据两个步骤,能够简便易行地实现订阅发布。
向 topic 推送数据
基于《redis 分布式缓存 springboot + redisson》中对 redisson 的依赖引入和初始化,使用 redissonClient.getTopic 获取 topic,并使用 topic.publish 发布消息。
@Service
@Slf4j
public class RedissonTopicObjServiceImpl implements IRedissonTopicObjService {
public static final String REDISSON_TOPIC_EMAIL_KEY = "Redisson:Email:Topic:Key:";
@Autowired
private UserMapper userMapper;
@Autowired
private RedissonClient redissonClient;
public void sendTopicEmail(final Integer userId){
User user = userMapper.selectByPrimaryKey(userId);
if(null!=user && StringUtils.isNotBlank(user.getEmail())){
log.info("userId:{} 的邮箱信息被投递到topic中",userId);
//将待发送的目标邮箱,放入到topic中,消费者读取该邮件,然后发送邮件
RTopic<String> toSendEMailAddress = redissonClient.getTopic(REDISSON_TOPIC_EMAIL_KEY);
toSendEMailAddress.publish(user.getEmail());
}
}
}
监听 topic 消费数据
写 ApplicationRunner 接口的实现类作为监听器,这个类就会一直在内存里,使用 topic.addListener 监听特定事件并处理。同时实现 Ordered 接口用于指定多个监听器的处理顺序。
@Service
@Slf4j
public class TopicConsumerService implements ApplicationRunner,Ordered {
@Autowired
private RedissonClient redissonClient;
@Override
public void run(ApplicationArguments args) throws Exception {
log.info("--跟随项目启动,不断监听并处理消费者数据--");
this.listenTopicData();
}
@Override
public int getOrder() {
return 1;
}
/**
* 监听并处理topic中的数据
*/
private void listenTopicData(){
try{
log.info("-----监听主题topic,并处理其中的数据-----");
RTopic<String> mailTopic = redissonClient.getTopic(RedisKeyConstant.REDISSON_TOPIC_EMAIL_KEY);
mailTopic.addListener((charSequence,s)->{
log.info("从topic中读取的信息为:{}",s);
});
}catch (Exception e){
log.error("-----监听主题,处理数据出现异常-----");
}
}
}
总结
综上,redisson 提供了一种简易实现的订阅发布,适用于访问量不大的情况,否则会使内存负担较重。