1.mq作用
异步 解耦 销峰
2.产品选型
Kafka
优点: 吞吐量非常大,性能非常好,集群高可用。
缺点:会丢数据,功能比较单一。
使用场景:日志分析、大数据采集
RabbitMQ
优点: 消息可靠性高,功能全面。
缺点:吞吐量比较低,消息积累会严重影响性能。erlang语言不好定制。
使用场景:小规模场景。
RocketMQ
优点:高吞吐、高性能、高可用,功能非常全面。
缺点:开源版功能不如云上商业版。官方文档和周边生态还不够成熟。客户端只支持java。
使用场景:几乎是全场景
3.消息队列如何保证消息不丢失
- RocketMQ:通过同步刷盘、同步复制和事务消息,保证消息不丢失,适合金融等高可靠性场景。
- RabbitMQ:通过 Publisher Confirm、镜像队列和手动提交 Offset,保证消息不丢失,适合企业级应用。
- Kafka:通过 acksall、副本机制和手动提交 Offset 等机制,保证消息不丢失,适合大数据和高吞吐场景。
4.消息的幂等性
其实就是要方式消费者重复消费消息的问题。
所有MQ产品并没有提供主动解决幂等性的机制,需要由消费者自行控制。
RocketMQ: 给每个消息分配了个MessageID。这个MessageID就可以作为消费者判断幂等的依据。这种方式不太建议。
最好的方式就是自己带一个有业务标识的ID,来进行幂等判断。OrderID
统一ID分配
consumer.subscribe("OrderTopic", "*"); consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> { for (MessageExt msg : msgs) { String orderId = msg.getKeys(); if (isProcessed(orderId)) { System.out.println("订单 " + orderId + " 已处理,跳过"); continue; } try { // 执行业务逻辑(插入数据库) saveOrderToDB(orderId, new BigDecimal("99.99")); // 标记为已处理(写入Redis) markAsProcessed(orderId); } catch (DuplicateKeyException e) { System.out.println("订单 " + orderId + " 已存在(唯一索引冲突)"); } } return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; }); // 判断是否已处理(Redis) private boolean isProcessed(String orderId) { return Boolean.TRUE.equals(redisTemplate.hasKey("ORDER_PROCESSED:" + orderId)); } // 标记为已处理(Redis) private void markAsProcessed(String orderId) { redisTemplate.opsForValue().set("ORDER_PROCESSED:" + orderId, "1", 1, TimeUnit.HOURS); } // 保存订单到数据库 private void saveOrderToDB(String orderId, BigDecimal amount) { String sql
Java与Redis面试题大揭秘

最低0.47元/天 解锁文章

46万+

被折叠的 条评论
为什么被折叠?



