第三面准备

准备网络面试题

如果让你实现一个MQ,怎么样保证消息不丢失?

MQ丢失数据存在两种情况,消费端丢失消息和MQ服务器丢失数据;

  • 生产者弄丢数据:在消息网络传输过程中因网络问题导致消息丢失。
  • MQ服务器弄丢数据:例如rabbitmq没有开启消息持久化,在服务器宕机后重启服务丢失;kafka某个broke宕机,重新选举partition leader时选举了一个还么有同步完消息的fllower作为leader就会丢失消息。
  • 消费端弄丢消息:消费端接收到消息,在业务处理过程中宕机 导致 消息丢失情况。

rabbitmq 如何防止消息丢失

生产者保证消息不丢失

  1. rabbitmq提供是事物功能,在发送消息的时候开启事务,如果发送时出现异常则回滚日志并尝试重新发送。发送消息变为同步阻塞过程,影响吞吐量
  2. confirm机制,rabbitmq开启confirm机制后每次发送消息,如果消息发送成功会毁掉ack接口,失败则毁掉nack接口。通过异步的方式保证消息发送

rabbitmq 服务器保证消息不丢失

rabbitmq开启消息持久化功能,将消息持久化到磁盘。并且可以结合confirm机制,在持久化成功后才毁掉ack接口通知成功。

消费者保证消息不丢失

rabbitmq提供ack机制,首先关闭自动ack机制,在每次消息处理完成后手动调用ack接口。

kafka 如何防止消息丢失

消费端保证消息不丢失

kafka关闭自动提交offset,在每次消息发送成功后手动提交offset。

kafka 保证消息不丢失

  1. kafka配置replication.factor 大于1,也就是每个topic有多个副本。
  2. kafka服务器配置min.isync.replicas 大于1,也就是保证至少有一个fllower可用
  3. 在生产者端设置acks=all,也就是要求全部副本写入之后才认为成功
  4. 在生产者端设置retries=MAX,表示失败无限重试写入

生产者保证消息不丢失

在生产者端设置retries=MAX,写入消息失败则多次尝试 保证写入消息成功。

mysql的innodb索引数据结构为什么是b+树,用hash来实现可以吗?

什么是索引

索引是为了提高mysql查询效率而存储在磁盘上的数据结构。为提高查询效率应该尽可能减少磁盘io。

索引常见数据结构

  1. 二叉树
    二叉树采用二分法思想,O(log N)的复杂度就可以完成对数据的查找任务,查找所需的最大次数等同于二叉查找树的高度。
    数的查询效率取决于数的高度,在极端情况下二叉树会退化为线性表。

  2. 平衡二叉树
    平衡二叉查找树(AVL树)在符合二叉查找树的条件下,还满足任何节点的两个子树的高度最大差为1。

  3. 红黑树
    红黑树是一种自平衡的二叉查找树。红黑树和平衡二叉树的区别如下:

  • AVL是严格平衡树,因此在增加或者删除节点的时候,根据不同情况,旋转的次数比红黑树要多;
  • 而红黑是弱平衡的,用非严格的平衡来换取增删节点时候旋转次数的降低;
  • 查找的次数远远大于插入和删除,那么选择AVL树;如果搜索、插入删除次数几乎差不多,应该选择RB树。

为什么使用B+树作为索引

B+树只需要遍历叶子节点就可以实现整棵树的遍历,而不需要遍历所有节点。B+树非叶子节点存储key而不存储data数据,相比于B-树他高度更矮 io效率更少。

hash作为索引:虽然hash可以快速定位但是无序 ,对于一次索引获取多个连续数据就会需要多次io
二叉树索引:不能自平衡,io代价高

秒杀如何防止超卖

秒杀系统超卖产生的原因

秒杀系统卖货是一个事务操作,涉及查询秒杀库存、更新购买后库存。例如库存是10个 在并发情况下,线程A查询到库存为10个 则生成订单并扣减库存8个;线程B在同一时刻也查询到库存为10个,也生成订单并扣减库存8个;两个线程执行完成后库存为-6 出现超卖问题。

超卖问题解决

序号 方法 优点 缺点
1 悲观锁 在更新库存期间加锁,不允许其它线程修改;select * for update 高并发情况下会导致多个请求等待数据库链接,数据库成为性能瓶颈
2 乐观锁 在数据库中添加版本号字段,修改数据时判断版本号 ----------
3 分布式锁 分布式锁是在业务代码中手动获取锁,并在业务处理完成后释放锁,在这一过程中其他线程无法获取锁 对同一商品的秒杀会出现多个线程等待分布式锁,系统吞吐量下降
4 FIFO 队列 引入串行化队列将所有的写数据库的请求在队列里边穿行化执行 性能受限于队列处理机处理性能和DB的写入性能中最短的那个
5 Redis原子操作 利用redis的事务特性,将库存数据缓存中redis中。秒杀库存直接操作redis,异步更新数据到db 保证数据一致性

ThreadLocal原理以及oom

ThreadLocal是操作线程的局部变量入口,可以为每个线程提供一个独立的变量副本。

ThreadLocal原理

ThreadLocal类在线程中声明,要注意不同实例的ThreadLocal 存储的变量副本不同。原理是ThreadLocal是一个操作线程本地变量ThreadLocalMap(一个Entity数组存储数据,可以理解为HashMap)的入口,并且以ThreadLocal 实例this作为key(弱引用);存储的具体值value为强引用。

ThreadLocal产生oom原因

ThreadLocalMap的生命周期于线程的生命周期一致,当应用ThreadLocal的对象被回收时,ThreadLocalMap还持有ThreadLocal的弱引用以及value的强引用;弱引用会在下次垃圾回收时回收,但强应用value无法回收 造成泄漏。

HashMap实现原理

数组+链表的散列存储结构,数组初始容量16,扩容因子0.75;超过最大存储容量则进行2被扩容处理;如果链表length>8 hash碰撞冲突太多,转换为红黑树存储(查询效率高于链表)。

你可能感兴趣的:(第三面准备)