面试题-16道必看

Java与Redis面试题大揭秘

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 
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值