淘宝面试总结

牛客上淘宝的HR主动要我简历然后就交了, 然后就参加了笔试, 笔试编程成绩其实还好, 基本AK, 然后就去牛客上找HR安排了电话面试, 然后我的噩梦开始

面试流程:

自我介绍

简历相关的问题:

  • 你这个通信工程专业和计算机相关的课程都是自学的吗?

  • 校内外的编程比赛没有参加过吗?

  • 项目是简历上只写了这一个但是没有其他的吗?

  • 这些项目都是自己写的吗?

  • 老师的项目有参加吗?

(真的好有侵略性, 这就是狼性文化的企业氛围吗)

Java

  • ThreadLocal 知道吗? 说一下使用场景和是实现原理 (清楚, 但是表达有点紧张)

  • 知道线程安全的概念吗? 说一下 (这个背忘了, 只是按照自己理解说了原子性和可见性)

  • 知道 Java 的静态代理和动态代理了解过吗, 简单说一下 (这是一个实习生该会的东西吗? 只说了一下自己知道的 Spring 的 AOP 代理, 然后 AOP 静态代理是编译阶段完成, 对字节码有侵入性, 但是 AOP 动态代理是运行时完成, 通过继承子类实现 )

  • Java 怎么实现动态代理 (不知道)

  • Java 的 filter? (没听清, 不知道问什么)

  • Java 的线程池了解过吗, 说一下为什么要线程池, 你是怎么使用的

  • Java 的锁了解过吗 (synconized 和 AQS), 说一下自己的看法, 自己怎么使用的 (我...能有什么看法, 答得比较乱, 没个思路大纲)

MySQL 相关

  • 数据库事务原理讲一下 (不知道要问什么? 后面才反应过来回答 ACID 就行了)
  • ACID 知道吗 (说了)
  • 数据库的事务隔离级别
  • 读已提交和可重复读的区别
  • MySQL InnoDB 默认隔离级别
  • MySQL 有一张表, 对 (A,B,C) 建立了联合索引, A=1 and B>1 and C=1 会导致索引失效吗 (我回答的不会, 看博客也说得不会, 但是面试官好像觉得是会的, 还没做实验验证, 去问了 gpt 也没有准确的答案)
  • MySQL 分库分表的解决方案 (直接用ShardingSphere)
  • 怎么理解 MySQL 为什么要分库分表, 什么情况下会分库分表
  • 分布式存储, 集群了解过吗
  • 什么是分布式锁
  • 实现分布式锁的有哪几种方式, 这几种方案有什么共同点和差异 (我只用过一种, 答得乱七八糟得)
  • redis 的分布式和集群有什么区别(不清楚要回答什么)

项目:

  • 项目做了多少时间?
  • 服务部署起来了吗? 服务器部署过吗, 电脑部署过吗?
  • 简单介绍一下这个短链接平台做了什么
  • 各种追问, 为什么用分布式锁, 为什么这么做, 数据库怎么设计的, 紧张到解释不清, 然后面试官基本就是表示不太理解
  • 还问了微服务之类的, 问了 nacos 和 dubbo 有实践过吗 (没有, 只是学习了文档)

其他问题

  • 排名多少?
  • 打算读研吗?
  • 研究生打算读什么专业? (人工智能)
  • 为什么找实习?
  • 为什么不找通信工程的研究生?

我说自己对读研没有那么大的意愿, 并且通信工程的竞争太过激烈, 有机会也打算读人工智能的研究生

亡羊补牢:

  • 什么是线程安全: 在拥有共享数据的多线程并行执行的程序中, 保证多线程并发的原子性, 可见性, 有序性

  • Java 的静态代理和动态代理: 静态代理和动态代理区别(是否有实现类), 通过代理实现控制对某个对象的访问

    静态代理: 由程序员创建代理类或特定工具自动生成源代码再对其编译。在程序运行前代理类的.class文件就已经存在了。

    Java中的静态代理要求代理类(ProxyObject)和委托类(RealObject)都实现同一个接口(Interface)。静态代理中代理类在编译期就已经确定,而动态代理则是JVM运行时动态生成,静态代理的效率相对动态代理来说相对高一些,但是静态代理代码冗余大,一旦需要修改接口,代理类和委托类都需要修改。

    动态代理: 在程序运行时运用反射机制动态创建而成。

    Java中的动态代理依靠反射来实现,代理类和委托类不需要实现同一个接口。委托类需要实现接口,否则无法创建动态代理。代理类在JVM运行时动态生成,而不是编译期就能确定。

  • Java 如何实现动态代理: Java动态代理主要涉及到两个类:java.lang.reflect.Proxyjava.lang.reflect.InvocationHandler。代理类需要实现InvocationHandler接口或者创建匿名内部类,而Proxy用于创建动态动态。

  • Java 锁的整合总结, 第一次遇到直接问这么大框架的问题的, 没回答全...

来自文心一言的总结, 还挺对的

Java中,synchronized关键字和ReentrantLock都是用于实现同步机制的工具,确保在多线程环境中对共享资源的访问是互斥的。

  1. 来源与实现:
    • synchronized是Java语言内置的关键字,由JVM实现,无需引入额外的类。
    • ReentrantLock是Java标准库中的一个类,它是基于AQS(AbstractQueuedSynchronizer)实现的,提供了比synchronized更丰富的功能。
  2. 锁的获取与释放:
    • synchronized的锁获取与释放是隐式的,由JVM自动管理。当方法或代码块执行完毕时,锁会自动释放。
    • ReentrantLock的锁获取与释放是显式的,需要手动调用lock()unlock()方法。这提供了更精细的控制,但也增加了出错的概率(例如,忘记释放锁)。
  3. 等待/通知机制:
    • synchronized通过wait()notify()notifyAll()方法支持等待/通知机制。
    • ReentrantLock则提供了Condition对象,可以创建多个等待集合,这使得等待/通知机制更加灵活。
  4. 可中断性:
    • synchronized是不可中断的,即线程在等待获取锁时不能响应中断。
    • ReentrantLock支持可中断获取锁,通过lockInterruptibly()方法,线程在等待获取锁时可以响应中断。
  5. 公平性:
    • synchronized不提供公平性保证,即等待时间最长的线程不一定会优先获得锁。
    • ReentrantLock可以通过构造函数指定公平锁或非公平锁。公平锁按照线程请求锁的顺序来获取锁,而非公平锁则允许插队。
  6. 性能:
    • 在竞争不激烈的情况下,synchronized的性能开销可能小于ReentrantLock,因为synchronized是JVM内置支持的。
    • 在竞争激烈的情况下,ReentrantLock的性能可能优于synchronized,因为它提供了更多的优化手段,如锁降级、锁升级等。
  7. 错误处理:
    • synchronized在出现异常时,JVM会自动释放锁。
    • ReentrantLock在出现异常时,需要确保在finally块中释放锁,否则可能导致死锁。
  • MySQL 有一张表, 对 (A,B,C) 建立了联合索引, A=1 and B>1 and C=1 会导致索引失效吗? 有待验证, 因为 小林coding 里面提到过只要满足最左匹配, 并且左边的索引没有失效, 那自己也不会失效, 但是一些博客又会说范围查询会导致失效的

  • 什么情况下会分库分表: 避免单一数据库的数据量过大导致的性能瓶颈, (比如主键索引B+数层数过深导致IO性能下降, 数据量过大导致的插入删除性能下降); 降低对单一节点的访问压力

  • 分布式存储集群: 如何实现, 读写分离分片, 提升性能和实现高可用, 便于扩展, 均衡负载

  • 什么是分布式锁: 类比多线程并发的锁, 分布式锁是分布式系统中用来控制多个分布式服务对共享资源访问的一种机制。

  • 分布式锁知道哪几种实现方式, 都有什么异同:

分布式锁的实现方式主要有三种:基于数据库、基于缓存(如Redis)以及基于Zookeeper。

相同点:

互斥(属于安全性):在任何给定时刻,只有一个客户端可以持有锁。

无死锁(属于有效性):即使锁定资源的客户端崩溃或被分区,也总是可以获得锁;通常通过超时机制实现。

容错性(属于有效性):只要大多数 Redis 节点都启动,客户端就可以获取和释放锁。

不同点:

  1. 基于SQL数据库实现分布式锁:

  • 基于唯一索引或者SQL数据库的互斥锁完成的分布式锁

  • 依赖数据库的读写性能, 并且单节点SQL数据库性能限制严重

  1. 基于Redis实现分布式锁:

  • 利用 set NX EX 命令实现 + lua 脚本保证原子性

  • 基于内存的操作效率更高, 响应速度更快, 性能更好

  • 对于多节点的 redis 集群可是考虑使用 redlock

  • 需要考虑Redis的持久化、备份和故障恢复等问题,以确保锁的可靠性。

  • redis 官方推荐 Redisson 实现的分布式锁

  1. 基于Zookeeper实现分布式锁:

  • 利用Zookeeper的临时节点和Watcher机制来实现分布式锁。客户端在Zookeeper上依次创建临时节点,最小的节点获得锁, 释放锁就删除节点, 实现公平锁。
  • Zookeeper提供了强一致性保证,确保锁的正确性和可靠性。
  • Zookeeper作为分布式协调服务,具有高可用性和可扩展性,适用于大型分布式系统。
  • 实现相对复杂,需要熟悉Zookeeper的API和原理。
  • redis 集群与 redis 分布式的区别是什么?: 分布式是指将业务系统进行拆分,即分布式的每一个节点都是实现不同的功能。集群是一组协同工作的服务实体,用以提供比单一服务实体更具扩展性与可用性的服务平台。

    简单说,分布式是以缩短单个任务的执行时间来提升效率的,而集群则是通过提高单位时间内执行的任务数来提升效率。

总结:

真是一场酣畅淋漓的破防啊