美团后端开发工程师二面

base:北京

到店事业群-平台技术部

##2021.8.27 美团 二面

1.自我介绍

2.实习项目介绍

3.HashMap

简单来说,HashMap由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的,如果定位到的数组位置不含链表(当前entry的next指向null),那么查找,添加等操作很快,仅需一次寻址即可;如果定位到的数组包含链表,对于添加操作,其时间复杂度为O(n),首先遍历链表,存在即覆盖,否则新增;对于查找操作来讲,仍需遍历链表,然后通过key对象的equals方法逐一比对查找。所以,性能考虑,HashMap中的链表出现越少,性能才会越好。

3.1 数据结构

jdk1.8以前是数组+链表
jdk1.8以后是数组+链表+红黑树

3.2 扩容

当HashMap中的元素越来越多的时候,hash冲突的几率也就越来越高,因为数组的长度是固定的。所以为了提高查询的效率,就要对HashMap的数组进行扩容,而在HashMap数组扩容之后,最消耗性能的点就出现了:原数组中的数据必须重新计算其在新数组中的位置,并放进去,这就是resize。 (具体理解还需百度)

3.3 扩容过程中链表如何迁移到新的位置

如果hash值第N+1位为0,则表示不需要调整该链表节点位置;如果为1,表示需要调整到 原索引+原数组长度的位置。

3.4 为什么线程不安全

在JDK1.7中,当并发执行扩容操作时会造成环形链和数据丢失的情况。
在JDK1.8中,在并发执行put操作时会发生数据覆盖的情况。

3.5 什么情况下成为一个环状

主要在这扩容的过程,当多个线程同时对这个HashMap进行put操作,而察觉到内存容量不够,需要进行扩容时,多个线程会同时执行resize操作,而这就出现问题了。首先,在HashMap扩容时,会改变链表中的元素的顺序,将元素从链表头部插入,而环形链表就在这一时刻发生。

4.CurrentHashMap

5.LRU是什么?如何实现

LRU是一种缓存淘汰机制策略。

6.平衡二叉树

它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。查找、插入和删除在平均和最坏情况下的时间复杂度都是O(logn)。

7.堆是什么?如何调整

堆就是用数组实现的二叉树,堆分为两种:最大堆和最小堆,性质如下:
(1)堆中某个节点的值总是不大于或不小于其父节点的值。
(2)堆总是一棵完全二叉树。

堆调整(堆的初始化):排序之前需要将序列调整为堆(不满足时 与 左右孩子中较大的那一个进行交换) 从n/2向下取整个点开始由后向前调整直到满足堆条件为止。

(1)从堆顶取出最大元素 ,堆顶元素与堆的最后一个元素交换位置 (往后就不用考虑当前最后一个元素)。
(2)对剩余的元素进行调整 , 调整选择剩下元素中的最大元素 (根与左右孩子中较大的那个进行交换直到满足条件为止)即 对根进行堆调整。
(3)重复以上过程 直到序列有序为止 (大堆升序)。

8.口述:二叉树最近的祖先节点

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null || root == p || root == q) {
            return root;
        }
        TreeNode pqInLeft = lowestCommonAncestor(root.left, p, q);
        TreeNode pqInRight = lowestCommonAncestor(root.right, p, q);
        if(pqInLeft == null) {
            return pqInRight;
        } else if(pqInRight == null) {
            return pqInLeft;
        } else {
            return root;
        }
    }

9.栈和队列,举个使用场景例子

栈是先进后出,队列是先进先出。时间复杂度都是O(1)。
栈和队列可以模拟很多现时的生产环境,例如洗盘子、排队。

10.MySQL为什么InnoDB是默认引擎

MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持。MyISAM类型的表强调的是性能,其执行数度比InnoDB类型更快,但是不提供事务支持,而InnoDB提供事务支持以及外部键等高级数据库功能。

MyISAM是非聚集引擎(索引和行记录分开存储) ,支持全文索引;不支持事务;它是表锁,会保存表的具体行数。MyISAM的表可以没有主键。
innoDB是聚集引擎(主键索引和行记录存储在一起),5.6以后才有全文索引;支持事务;它是行锁,不会保存表的具体行数。

11.MySQL为什么使用B+ 树

大大降低了树高度,可以减少IO次数
可以充分利用磁盘,存储更多的key
可以很快的遍历,范围查询,排序等

12.B+树的叶子节点链表是单向还是双向

双向,用于倒序

13.MVCC是什么?作用?

多版本并发控制(MVCC)

作用:
(1)MVCC在MySQL InnoDB中的实现主要是为了提高数据库并发性能,用更好的方式去处理读-写冲突,做到即使有读写冲突时,也能做到不加锁,非阻塞并发读
(2)我们都知道并发访问数据库造成的四种问题(脏写(修改丢失)、脏读、不可重复读、幻读),MVCC就是在尽量减少锁使用的情况下高效避免这些问题

14.更新是如何保证一致的?

当前读

15.如何回滚一条记录?

undo log

16.undo log具体怎么回滚

举个例子:
对于 insert 类型的sql,会在undo log中记录下方才你insert 进来的数据的ID,当你想roll back时,根据ID完成精准的删除。
对于delete类型的sql,会在undo log中记录方才你删除的数据,当你回滚时会将删除前的数据insert 进去。
对于update类型的sql,会在undo log中记录下修改前的数据,回滚时只需要反向update即可。
对于select类型的sql,别费心了,select不需要回滚。

17.如何查询慢sql产生的原因

(1)没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷)
(2)I/O吞吐量小,形成了瓶颈效应。
(3)没有创建计算列导致查询不优化。
(4)内存不足
(5)网络速度慢
(6)查询出的数据量过大(可以采用多次查询,其他的方法降低数据量)
(7)锁或者死锁(这也是查询慢最常见的问题,是程序设计的缺陷)
(8)sp_lock,sp_who,活动的用户查看,原因是读写竞争资源。
(9)返回了不必要的行和列
(10)查询语句不好,没有优化

18.索引失效的情况

(1)如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因)
(2)对于多列索引,不是使用的第一部分(第一个),则不会使用索引
(3)like查询是以%开头
(4)如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引
(5)如果mysql估计使用全表扫描要比使用索引快,则不使用索引

19.redis数据集合

20.有序集合

20.1 应用场景、底层实现

20.2 为什么数据量小的时候用压缩列表

20.3 压缩列表 跳跃表的区别

21.redis主从复制

21.1 原理

主从复制过程大体可以分为3个阶段:连接建立阶段(即准备阶段)、数据同步阶段、命令传播阶段。

在从节点执行 slaveof 命令后,复制过程便开始运作,下面图示可以看出复制过程大致分为6个过程。

主从配置之后的日志记录也可以看出这个流程。

1、保存主节点(master)信息

执行 slaveof 后 Redis 会打印如下日志:

2、从节点与主节点建立网络连接

从节点(slave)内部通过每秒运行的定时任务维护复制相关逻辑,当定时任务发现存在新的主节点后,会尝试与该节点建立网络连接。

从节点与主节点建立网络连接。

从节点会建立一个 socket 套接字,从节点建立了一个端口为51234的套接字,专门用于接受主节点发送的复制命令。从节点连接成功后打印如下日志:

如果从节点无法建立连接,定时任务会无限重试直到连接成功或者执行 slaveofnoone 取消复制。

关于连接失败,可以在从节点执行 info replication 查看 master_link_down_since_seconds 指标,它会记录与主节点连接失败的系统时间。从节点连接主节点失败时也会每秒打印如下日志,方便发现问题。

3、发送 ping 命令

连接建立成功后从节点发送 ping 请求进行首次通信, ping 请求主要目的如下:

检测主从之间网络套接字是否可用。

检测主节点当前是否可接受处理命令。

如果发送 ping 命令后,从节点没有收到主节点的 pong 回复或者超时,比如网络超时或者主节点正在阻塞无法响应命令,从节点会断开复制连接,下次定时任务会发起重连。

从节点发送的 ping 命令成功返回,Redis 打印如下日志,并继续后续复制流程:

4、权限验证

如果主节点设置了 requirepass 参数,则需要密码验证,从节点必须配置 masterauth 参数保证与主节点相同的密码才能通过验证。如果验证失败复制将终止,从节点重新发起复制流程。

5、同步数据集

主从复制连接正常通信后,对于首次建立复制的场景,主节点会把持有的数据全部发送给从节点,这部分操作是耗时最长的步骤。

6、命令持续复制

当主节点把当前的数据同步给从节点后,便完成了复制的建立流程。接下来主节点会持续地把写命令发送给从节点,保证主从数据一致性。

主从复制的作用

1、数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。

2、故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。

3、负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。

4、读写分离:可以用于实现读写分离,主库写、从库读,读写分离不仅可以提高服务器的负载能力,同时可根据需求的变化,改变从库的数量。

5、高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。

21.2 通过什么复制?

RDB

21.3 增量复制命令存在哪里?

缓冲区

22.RDB AOF优缺点

Redis的持久化策略:2种

  • RDB:快照形式是直接把内存中的数据保存到一个 dump 文件中,定时保存,保存策略。

  • AOF:把所有的对Redis的服务器进行修改的命令都存到一个文件里,命令的集合。

RDB 的优点

这种文件非常适合用于进行备份: 比如说,你可以在最近的 24 小时内,每小时备份一次 RDB 文件,并且在每个月的每一天,也备份一个 RDB 文件。 这样的话,即使遇上问题,也可以随时将数据集还原到不同的版本。RDB 非常适用于灾难恢复(disaster recovery)。

RDB 的缺点

如果你需要尽量避免在服务器故障时丢失数据那么 RDB 不适合你。 虽然 Redis 允许你设置不同的保存点(save point)来控制保存 RDB 文件的频率, 但是, 因为RDB 文件需要保存整个数据集的状态, 所以它并不是一个轻松的操作。 因此你可能会至少 5 分钟才保存一次 RDB 文件。 在这种情况下, 一旦发生故障停机, 你就可能会丢失好几分钟的数据

AOF 的优点

使用 AOF 持久化会让 Redis 变得非常耐久(much more durable):你可以设置不同的 fsync 策略,比如无 fsync ,每秒钟一次 fsync ,或者每次执行写入命令时 fsync 。 AOF 的默认策略为每秒钟 fsync 一次,在这种配置下,Redis 仍然可以保持良好的性能,并且就算发生故障停机,也最多只会丢失一秒钟的数据( fsync 会在后台线程执行,所以主线程可以继续努力地处理命令请求)。

AOF 的缺点

对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB在一般情况下, 每秒 fsync 的性能依然非常高, 而关闭 fsync 可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间(latency)。

23.spring AOP原理及好处

Spring的AOP使用了两种动态代理,分别是JDK的动态代理,以及CGLib的动态代理。

降低模块的耦合度
使系统容易扩展
提高代码复用性

24.bean的初始化过程

1.Spring启动,查找并加载需要被Spring管理的bean,进行Bean的实例化
2.Bean实例化后对将Bean的引入和值注入到Bean的属性中
3.如果Bean实现了BeanNameAware接口的话,Spring将Bean的Id传递给setBeanName()方法
4.如果Bean实现了BeanFactoryAware接口的话,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入
5.如果Bean实现了ApplicationContextAware接口的话,Spring将调用Bean的setApplicationContext()方法,将bean所在应用上下文引用传入进来。
6.如果Bean实现了BeanPostProcessor接口,Spring就将调用他们的postProcessBeforeInitialization()方法。
7.如果Bean 实现了InitializingBean接口,Spring将调用他们的afterPropertiesSet()方法。类似的,如果bean使用init-method声明了初始化方法,该方法也会被调用
8.如果Bean 实现了BeanPostProcessor接口,Spring就将调用他们的postProcessAfterInitialization()方法。
9.此时,Bean已经准备就绪,可以被应用程序使用了。他们将一直驻留在应用上下文中,直到应用上下文被销毁。
10.如果bean实现了DisposableBean接口,Spring将调用它的destory()接口方法,同样,如果bean使用了destory-method 声明销毁方法,该方法也会被调用。

25.算法题:topK (力扣 215. 数组中的第K个最大元素)

public int findKthLargest(int[] nums, int k) {
        Queue<Integer> heap = new PriorityQueue<>();
        for(int num : nums) {
            if(heap.size() < k) {
                heap.add(num);
            } else if(heap.peek() < num) {
                heap.remove();
                heap.add(num);
            }
        }
        return heap.peek();
    }

26.通过什么方式学习

27.反问

##2021.8.30 三面HR面

1.自我介绍

2.优缺点

3.目前的offer、实习转正、美团这些公司如何考虑

4.职业规划

5.最看重公司的什么

6.其他一些基本情况


版权声明:本文为qq_45803603原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。