鼠の面试题

86 阅读7分钟

MQ如何保证消息不丢失

生产者:发送确认机制

mq本身:做好持久化、容灾备份-队列的副本机制

消费者:消费ack确认机制-让mq重新投递

可能消息丢失的环节

1、生产者发送消息丢失

kafka:消息发送+回调

RocketMQ:1、消息发送+回调

   2、事务消息机制

RabbitMQ:1、消息发送+回调

2、手动事务:channel.txSelect()开启事务,channel.txCommit()提交事务,channel.txRollback()回滚事务。这种方式对channel是会产生阻塞,造成吞吐量下降

3、Publisher Confirm 整个处理流程跟RocketMQ的事务消息,基本一样

2、MQ主从同步消息丢失 同步和异步同步

RocketMQ:1、普通集群中,同步同步、异步同步。异步同步效率更高,但有消息丢失的风险,同步同步就不会丢失消息

   2、Dledger集群-两阶段提交(当大部分Slave节点同步完成,Uncommited状态变为commited状态)

  每次生产者发送消息,Dledger都会重新选举出Master节点

RabbitMQ:1、普通集群:消息是分散存储,节点之间不会主动进行消息同步

  2、镜像集群:镜像集群会在节点之间主动进行数据同步,这样数据安全性会得到提高

kafka:通常都是用在允许消息少量丢失的场景。acks:0 , 1, all

3、MQ消息存盘丢失

RocketMQ:同步刷盘 异步刷盘:异步刷盘效率更高,但是有可能丢消息。同步刷盘消息安全性更高,但是效率会降低

RabbitMQ:将队列配置成持久化队列。新增的Quorum类型的队列,会采用Raft协议来进行消息同步

4、MQ消费者消费消息丢失

RocketMQ:使用默认的方式消费就行,不要采用异步方式

RabbitMQ:autoCommit -> 手动提交offset

Kafka:手动提交offset

消息队列如何保证消息可靠传输

消息可靠传输代表了两层意思,既不能多也不能少。

1.为了保证消息不多,也就是消息不能重复,也就是生产者不能重复生产消息,或者消费者不能重复消费消息

2、首先要确保消息不多发,这个不常出现,也比较难控制,因为如果出现了多发,很大的原因是生产者自己的原因,如果要避免出现问题,就需要在消费端做控制

3、要避免不重复消费,最保险的机制就是消费者实现幂等性,保证就算重复消费,也不会有问题,通过幂等性,也能解决生产者重复发送消息的问题

4、消息不能少,意思就是消息不能丢失,生产者发送的消息,消费者一定要能消费到,对于这个问题,就要考虑两个方面

5、生产者发送消息时,要确认broker确实收到并持久化了这条消息,比如RabbitMQ的confirm机制,Kafka的ack机制都可以保证生产者能正确的将消息发送给broker

6、broker要等待消费者真正确认消费到了消息时才删除掉消息,这里通常就是消费端ack机制,消费者接收到一条消息后,如6.果确认没问题了,就可以给broker发送一个ack,broker接收到ack后才会删除消息

MQ如何保证消息顺序消费

全局有序和局部有序:MQ只需要保证局部有序,不需要保证全局有序

生产者把一组有序的消息放到同一个队列当中,而消费者一次消费整个队列当中的消息

RocketMQ中有完整的设计,但是在RabbitMQ和kafka当中,并没有完整的设计,需要自己进行设计

RabbitMQ:要保证目标exchange只对应一个队里了。并且一个队列只对应一个消费者

kafka:生产者通过定制partition分配规则,将消息分配到同一个partition。Topic下只对应一个消费者

如何保证消息的高效读写

零拷贝:kafka和RocketMQ都是通过零拷贝技术来优化文件读写

传统文件复制方式:需要堆文件在内存中进行四次拷贝

零拷贝:有两种方式 mmap和transfile

mmap: MappedByteBuffer

transfile:

Java对零拷贝进行了封装,mmap方式通过MappedByteBuffer对象进行操作,而transfile通过FileChannel来进行操作

mmap适合比较小的文件,通常文件大小不要超过1.5G~2G之间

Transfile没有文件大小限制

RocketMQ当中使用mmap方式来对他的文件进行读写。commitlog 1G

在kafka当中,他的index日志文件也是通过mmap的方式来读写的。在其他日志文件当中,并没有使用零拷贝的方式

kafka使用transfile方式将硬盘数据加载到网卡

Redis持久化

|-rdb快照(save、bgsave)- save 1 ,10, save 5 ,60 、 aof命令(每条命令)

|-rdb优缺点:数据恢复快、存在数据丢失的可能-可靠性低

|-aof优缺点:文件大,数据可靠性高,数据恢复慢

|-rdb结合aof:rdb做定期的备份+aof增量的持久化

Redis 大Key问题 热Key问题

大Key问题:

Redis大key问题指的是某个key对应的value值所占的内存空间比较大,导致Redis的性能下降、内存不足、数据不均衡以及主从同步延迟等问题。

到底多大的数据量才算是大key?

没有固定的判别标准,通常认为字符串类型的key对应的value值占用空间大于1M,或者集合类型的k元素数量超过1万个,就算是大key。

Redis大key问题的定义及评判准则并非一成不变,而应根据Redis的实际运用以及业务需求来综合评估。例如,在高并发且低延迟的场景中,仅10kb可能就已构成大key;然而在低并发、高容量的环境下,大key的界限可能在100kb。因此,在设计与运用Redis时,要依据业务需求与性能指标来确立合理的大key阈值。

怎么解决:拆分

对于无法拆分的:放本地缓存

热Key问题

1、二级缓存(本地缓存)

当出现热 Key 以后,把热 Key 加载到系统的 JVM 中。后续针对这些热 Key 的请求,会直接从 JVM 中获取,而不会走到 Redis 层。这些本地缓存的工具很多,比如 Ehcache,或者 Google GuavaCache 工具,或者直接使用 HashMap 作为本地缓存工具都是可以的。

2、单独迁移到热点redis集群中去。

MySQL索引跳跃

MySQL一定是遵循最左前缀匹配的,这句话在以前是正确的,但是在MySQL 8.0出现了索引跳跃扫描。

MySQL 8.0.13 版本中,对于range查询引入了索引跳跃扫描(Index Skip Scan)优化,支持不符合组合索引最左前缀原则条件下的SQL,依然能够使用组合索引,减少不必要的扫描。

举例:

表中索引为:(a,b,c)

SQL语句为:

select a from tb where c>40;

该sql不符合最左前缀匹配,在以前版本的mysql不会用到索引

原理:

首先获取a,b字段的值,例如a=1,b=1;然后构造 where a=1 and b=1 and c>40;进行范围查询

一直到扫描完了a字段所有的唯一值,b字段的所有唯一值,最后将结果合并返回;

使用该策略可以减少访问的行数,因为会跳过不符合构造范围的行。

限制条件:

不能联表查询

不能使用group by聚合,以及distinct

查询的字段必须为索引中的列

MySQL 使用 like “%x“,索引一定会失效吗?

xiaolincoding.com/mysql/index…