面试题笔记01

记录一下看过的一些面试题。

封面
这位画师的脸以及上色很有特点,稍微留意一下很容易就能够辨别出来了,只是表情总给人一种同样的感觉w
https://twitter.com/__LM7__/status/1379416474293465090

MQ接收到消息后无法查询到或者是旧的状态

原因

  • 数据库回滚
  • 数据库事务未提交

解决办法

  • 可以尝试将mq放在数据库事务之后执行。
  • 可以利用@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)监听spring事务afterCommit阶段。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    @Transactional
    public boolean saveFoo(FooEntity fooEntity) throws InterruptedException {
    log.error("start insert foo");
    fooRepository.save(fooEntity);
    publisher.publishEvent(new MyTransactionEvent(fooEntity.getFooName()));
    log.error("end insert foo");
    Thread.currentThread().sleep(2000);
    log.error("to commit insert");
    return true;
    }
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void afterCommit(MyTransactionEvent event) {
    log.error("after commit then send event {}", event);
    log.error("after commit then send event {}", event.getName());
    }
    发送的spring事件会在监听到AFTER_COMMIT时执行
    参考:https://blog.csdn.net/little_kelvin/article/details/111330768

MQ偶然接收到重复消息

接收端消费了消息但是没有向broker发送ack或者broker没有接收到ack,导致broker将消息再次入队被其他接收端或同一个接收端消费,造成了重复消费消息

接收端方法做幂等:
新增,则可以在消息做一个唯一主键,重复了则会异常,保证数据库没有脏数据。
修改,一般都为幂等,修改多少次一般都是一样的结果。

如果还是比较困难,则用redis记录每次消费并生成全局唯一键<id,message>,每次消费查询一次redis,存在消费记录则不进行消费(处理)

熔断与服务降级

当请求某个服务超时或是响应过慢,并在一定时间内次数达到一定阈值,为了防止调用链路响应过长而引发的服务雪崩,我们将暂时不去请求这个服务, 而是调用降级方法,并下线该服务。期间一般会在过去一定时间后,尝试再次请求该服务,获得响应后才会上线,不然都将是调用降级方法。

例如Hystrix,它有一个滑动时间窗的概念,在这个滑动的时间窗内(默认20s),错误率达到阈值(默认50%)则将打开熔断器,并经过一段时间之后(默认5s)再次执行一次检测是否应该打开熔断器。
熔断器在打开期间,调用此服务将直接返回失败(服务降级),不再远程调用。

注意
服务降级不一定伴随着熔断出现,他还可能是开关降级、限流降级。
但是熔断是一定会出现服务降级的。
即熔断是服务降级的子集

ps: 服务雪崩是指由于调用链路当中,下游的服务响应太慢或者超时导致上游服务的请求得不到释放, 逐渐导致连接数达到上限从而又对上游服务造成影响 ,如此往复直到最上游服务难以承受压力(超过最大连接数等)


面试题笔记01
https://blog.kurenai.moe/2021/05/17/interview-note-01/
作者
Kurenai
发布于
2021年5月17日
许可协议