一、课程介绍
【课程名称】SpringBoot 2.x 实战仿B站高性能后端项目。
【章节】第三章3.29、3.30、3.31 生产消费动态,查询用户动态
【讲师】HELLOSTAR
二、课程内容
使用场景:
视频主发布动态之后,所有关注该视频主的用户都能得到消息推送。
实现逻辑:
----使用redis数据库的hash存储每个用户的所有订阅动态。每个用户的key为“subscribed”+用户id,value为用户动态集合;
----视频主发布动态之后,使用MQ的生产者发送该动态消息,消费者消费消息,并将该动态添加到每个粉丝在redis中存储的订阅动态集合中。保证Redis中存储的始终是用户当前所有的订阅动态。
-
新增用户动态
在用户动态表(userMoments)中插入一条数据,包含视频主用户id,动态内容,发布时间等信息。
调用默认配置的生产者(分组已命名),使用MQ发送一条消息。public void addUserMoments(UserMoment userMoment) throws Exception { userMoment.setCreateTime(new Date()); userMomentsDao.addUserMoments(userMoment); DefaultMQProducer producer = (DefaultMQProducer)applicationContext.getBean("momentsProducer"); Message msg = new Message(UserMomentsConstant.TOPIC_MOMENTS, JSONObject.toJSONString(userMoment).getBytes(StandardCharsets.UTF_8)); RocketMQUtil.syncSendMsg(producer, msg); }
-
消费用户动态
消费者的消息监听器一旦监听到生产者(相同分组中的)有消息发送,在消息监听器中获取到信息。
使用json工具类将消息装换成userMoments类型。获取发布消息的用户id;
得到该用户的所有粉丝,将该动态userMoments作为值存入到该用户的消息通知队列中。
使用redis来存储每个用户的通知消息队列,key为“subscribed”+用户id,value为需要通知的动态集合。//消费者 @Bean("momentsConsumer") public DefaultMQPushConsumer momentsConsumer() throws Exception{ DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(UserMomentsConstant.GROUP_MOMENTS); consumer.setNamesrvAddr(nameServerAddr); consumer.subscribe(UserMomentsConstant.TOPIC_MOMENTS, "*"); consumer.registerMessageListener(new MessageListenerConcurrently() { @Override public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context){ //获取消息 MessageExt msg = msgs.get(0); if(msg == null){ return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; } String bodyStr = new String(msg.getBody()); //解析消息中的用户动态 UserMoment userMoment = JSONObject.toJavaObject(JSONObject.parseObject(bodyStr), UserMoment.class); Long userId = userMoment.getUserId(); List<UserFollowing>fanList = userFollowingService.getUserFans(userId); for(UserFollowing fan : fanList){ String key = "subscribed-" + fan.getUserId(); //1.得到该粉丝目前的所有消息 String subscribedListStr = redisTemplate.opsForValue().get(key); List<UserMoment> subscribedList; if(StringUtil.isNullOrEmpty(subscribedListStr)){ subscribedList = new ArrayList<>(); }else{ subscribedList = JSONArray.parseArray(subscribedListStr, UserMoment.class); } //2.加入新消息 subscribedList.add(userMoment); //3.将最新的所有消息保存在Redis中 redisTemplate.opsForValue().set(key, JSONObject.toJSONString(subscribedList)); } return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; } }); consumer.start(); return consumer; }
-
查询订阅动态
获取当前用户id,拼接redis中保存用户通知消息的key。根据key查询得到的value即是当前用户订阅的动态集合。public List<UserMoment> getUserSubscribedMoments(Long userId) { String key = "subscribed-" + userId; String listStr = redisTemplate.opsForValue().get(key); return JSONArray.parseArray(listStr, UserMoment.class); }
三、课程收获
开发实现MQ中简单的消息生产和消费的过程。没有使用中间代理来转发消息。
四、学习过程
共同学习,写下你的评论
评论加载中...
作者其他优质文章