2023-10-8讯飞大模型部署2024秋招后端一面(附详解)

1 mybatis的mapper是什么东西

在MyBatis中,mapper是一个核心概念,它起到了桥梁的作用,连接Java对象和数据库之间的数据。具体来说,mapper可以分为以下两个部分:

  1. Mapper XML文件

    • 这是一个XML文件,其中定义了SQL语句和映射规则。每个SQL语句都有一个唯一的ID,这样Java代码可以引用它。
    • 在这个文件中,你可以定义CRUD操作(如<select>, <insert>, <update>, <delete>)。
    • 你还可以定义结果映射(如<resultMap>),这样你可以控制数据库结果集如何映射到Java对象。
  2. Mapper接口

    • 这是一个Java接口,它的方法与Mapper XML文件中的SQL语句ID相对应。
    • 你不需要为这个接口提供实现。MyBatis会在运行时为你生成实现,这通常是通过代理实现的。
    • 当你调用这个接口的方法时,MyBatis会执行对应的SQL语句,并返回结果。

这两部分结合在一起,允许你在Java代码中以面向对象的方式操作数据库,而不需要直接编写SQL语句。

例如,假设你有一个User类和一个对应的UserMapper接口。你可以在UserMapper.xml文件中定义一个<select>操作来获取一个用户,然后在UserMapper接口中定义一个相应的方法。当你调用这个方法时,MyBatis会执行XML文件中的SQL语句,并将结果映射到User对象。

总的来说,MyBatis的mapper提供了一个高级、面向对象的方式来操作数据库,它隐藏了底层的SQL细节,使得数据库操作更加简洁和直观。

2 mysql

2.1 mysql的索引数据结构,为什么用这个

3 redis

3.1 redis能做哪些事情

Redis是一个高性能的键值对存储系统,它支持的数据结构非常丰富,包括字符串(String)、哈希(Hash)、列表(List)、集合(Set)、有序集合(Sorted Set)等。因此,Redis可以用于以下场景:

  • 缓存:减少数据库的访问压力,提高应用的响应速度。
  • 会话存储:例如Web应用中的用户会话。
  • 消息队列:使用List数据结构实现。
  • 发布/订阅系统:支持消息的发布和订阅。
  • 计数器:例如网站访问计数。
  • 实时分析:例如实时统计用户的行为。
  • 排行榜/计分板:使用Sorted Set数据结构。
  • 地理空间索引:例如查找附近的地点。
  • **分布式锁:**redission分布式锁基于redis实现,预防缓存穿透

3.2 你手写一个分布式锁是怎么实现的

3.3 redis分布式锁实现的时候,具体用到了什么命令

答:实现Redis分布式锁主要用到以下命令:

  • SETNX key value:只有在键不存在时才设置值。
  • EXPIRE key seconds:为键设置一个过期时间,以防止死锁。
  • DEL key:释放锁,删除键。

在新版本的Redis中,可以使用SET key value NX EX seconds命令结合SETNXEXPIRE的功能。

3.4 缓存击穿的问题,除了使用分布式锁,还有别的方案呢?

答:

我的答案:设置两级缓存,两级缓存中的同一个键值对设置的过期时间是不一样的

使用两级缓存是一个很好的方法来防止缓存击穿。两级缓存通常包括一个本地缓存和一个分布式缓存。本地缓存通常使用LRU(最近最少使用)策略,而分布式缓存可能是基于Redis或Memcached的。

对于同一个键值对设置不同的过期时间,这是一个有效的策略。例如,你可以在本地缓存中设置一个较短的过期时间,而在分布式缓存中设置一个较长的过期时间。当本地缓存中的值过期时,应用可以从分布式缓存中获取值,而不是直接查询数据库。这样,即使分布式缓存中的值也过期,只有一个线程会去数据库中查询,其他线程会等待并从缓存中获取更新后的值。

这种策略可以有效地减少对数据库的访问,特别是在高并发的情况下。但需要注意的是,两级缓存会增加系统的复杂性,需要确保两个缓存之间的同步和一致性。

4 spring

4.1 用过异步编程吗

答:用过CompletableFuture

4.2 哪些场景下用过CompletableFuture

答:

  • 并行数据加载:例如,当需要从多个数据源并行加载数据时。
  • 异步API调用:例如,调用多个远程服务并在所有服务响应后进行数据聚合。
  • 异步计算 :对于计算密集型任务,可以使用CompletableFuture并行执行。

4.3 你用spring+mybatis构建web应用的时候,发现某一些请求特别慢,你怎么排查呢

排查慢请求:

如果有一些请求非常慢,以下是一些排查的步骤:

  1. 日志分析

    • 记录每个请求的响应时间。许多现代的web框架和服务器都允许你在日志中记录请求的响应时间。
    • 使用日志分析工具或脚本来识别响应时间超过预期阈值的请求。
  2. 性能监控工具

    • 使用如New Relic、Dynatrace、Datadog等性能监控工具,它们可以提供实时的应用性能指标,并帮助你识别慢请求。
  3. 分析请求和响应

    • 查看慢请求的输入参数、HTTP头、负载等,以确定是否有特定的模式导致延迟。
    • 分析响应内容,看是否有大量的数据被返回,这可能导致延迟。
  4. 数据库查询优化

    • 如果应用依赖于数据库,使用慢查询日志来识别和优化慢查询。
    • 使用数据库的性能分析工具来查看查询执行计划。
  5. 代码分析

    • 使用代码分析工具,如Java的JProfiler或VisualVM,来查看哪部分代码执行最慢。
  6. 外部服务

    • 如果应用调用外部服务或API,确保这些服务的响应时间是可接受的。
    • 使用工具如tracerouteping来检查网络延迟。

4.4 内存泄漏的排查:

内存泄漏是指应用程序在不再需要时,未能释放已分配的内存。以下是可能导致内存泄漏的情况和排查方法:

  1. 常见导致内存泄漏的情况

    • 静态集合类:长时间持有对象引用的静态集合。
    • 监听器和其他回调:没有被正确注销的监听器或回调。
    • 内部类和匿名类:非静态内部类或匿名类持有外部类的引用。
    • 线程池:长时间运行的线程持有对象引用。
    • 类加载器:当类加载器持有类的引用时,这些类不能被垃圾收集。
  2. 排查方法

    • Java堆转储 :使用工具如jmap来获取堆转储,并使用MAT(Memory Analyzer Tool)或其他工具来分析。
    • 分析工具:使用如VisualVM、JProfiler等工具来监视应用的内存使用情况。
    • GC日志:开启GC日志并分析,查看是否有大量的Full GC事件。
    • 代码审查:定期审查代码,特别是那些处理资源和对象生命周期的部分。

通过上述方法,可以有效地识别和解决应用中的慢请求和内存泄漏问题。

4.5 MAT工具能够分析出这些发生的内存泄露嘛,怎么识别呢

MAT(Memory Analyzer Tool)是一个强大的Java堆分析工具,它可以帮助开发者识别内存泄露和其他内存问题。以下是如何使用MAT来识别内存泄露的步骤:

  1. 获取堆转储文件 :首先,你需要从受影响的Java应用程序获取一个堆转储文件。这通常可以通过JVM的jmap工具或其他相关工具来完成。

  2. 打开堆转储文件:启动MAT并打开你的堆转储文件。

  3. 使用"Leak Suspects"报告:MAT提供了一个名为"Leak Suspects"的报告,它会尝试识别可能的内存泄露。这是一个很好的起点,因为它会列出可能的泄露对象和它们在堆中的大小。

  4. 分析对象的路径:为了确定一个对象为什么还在内存中(即它为什么没有被垃圾回收),你可以查看该对象到GC Roots的路径。这可以帮助你识别哪些对象或引用链导致了内存泄露。

  5. 查看大的对象实例:MAT允许你查看堆中最大的对象实例。这可以帮助你识别那些占用大量内存但可能不需要的对象。

  6. 使用查询和过滤:MAT提供了一个基于OQL(Object Query Language)的查询系统,允许你执行查询来查找特定的对象或模式。

  7. 查看线程和类加载器信息:有时,内存泄露可能与特定的线程或类加载器相关。MAT允许你查看这些信息,这可以帮助你进一步定位问题。

  8. 比较堆转储:如果你有多个堆转储文件(例如,从应用程序运行的不同时间点),你可以使用MAT来比较它们。这可以帮助你识别内存使用的增长趋势和可能的泄露点。

识别内存泄露通常需要一些经验和对应用程序的深入了解。MAT提供了很多有用的工具和视图来帮助你,但最终,你需要结合这些信息和你对应用程序的知识来确定和修复内存泄露。

5 多线程

5.1 使用多线程的时候注意哪些问题

我的答案:并发安全、硬件资料的消耗问题,在这两方面做一个tradeoff

使用多线程时,需要注意以下问题以确保线程安全、高效和可维护的代码:

  1. 数据竞争和条件竞争

    • 当多个线程尝试同时访问和修改共享数据时,可能会导致数据不一致。为了避免这种情况,需要使用适当的同步机制,如synchronized关键字、ReentrantLock等。
  2. 死锁

    • 当两个或多个线程永久地等待彼此释放资源时,会发生死锁。为了避免死锁,需要确保按照固定的顺序获取锁,并使用工具如jstack来检测和诊断死锁。
  3. 活锁

    • 当线程不断地尝试执行某个操作,但总是失败并重试时,可能会发生活锁。虽然线程是活跃的,但它们无法向前进展。
  4. 资源耗尽

    • 创建过多的线程可能会导致系统资源耗尽。使用线程池如ExecutorService可以帮助管理和限制线程的数量。
  5. 线程安全性

    • 不是所有的Java类和库都是线程安全的。在多线程环境中使用它们时,需要确保适当的同步。
  6. 线程间通信

    • 线程间需要合适的通信机制,如wait()notify()BlockingQueue等,以确保正确的协作。
  7. 线程优先级和饥饿

    • 设置线程的优先级可能会导致线程饥饿,即低优先级的线程得不到执行。通常,最好避免修改线程的优先级。
  8. 任务划分和粒度

    • 为了获得最佳的并发性能,需要合理地划分任务。太大的任务可能会导致其他线程等待,而太小的任务可能会导致过多的线程切换开销。
  9. 异常处理

    • 在多线程环境中,需要确保适当地处理异常,否则可能会导致线程意外终止。
  10. 可见性问题

    在没有适当同步的情况下,线程对变量的修改可能不会被其他线程看到。使用volatile关键字或其他同步机制可以确保变量的可见性。

  11. 上下文切换开销

    频繁的上下文切换会导致性能下降。尽量减少锁的竞争和线程的数量可以帮助减少上下文切换。

  12. 测试和调试

    多线程代码比单线程代码更难测试和调试。使用工具如Java Concurrency in Practice和专门的并发测试库可以帮助识别问题。

总之,多线程编程是复杂的,需要深入的理解和经验来确保正确和高效的代码。

6 消息队列

6.1 kafka的消息积压问题怎么解决呢?

Kafka的消息积压问题通常是指消费者不能及时处理生产者发送的消息,导致消息在Kafka中堆积。以下是一些建议的解决方案:

  1. 增加消费者数量

    • 如果消费者处理能力不足,可以增加消费者的数量。在Kafka中,可以通过增加消费者组中的消费者实例来实现。
  2. 优化消费者处理速度

    • 优化消费者的处理逻辑,确保每条消息都能够快速被处理。
    • 如果消费者需要进行复杂的处理,如数据库操作,可以考虑使用缓存或批量操作来提高效率。
  3. 调整Kafka参数

    • 调整fetch.min.bytesfetch.max.wait.ms参数,使消费者能够更频繁地从Kafka中拉取数据。
    • 调整max.poll.records参数,使消费者每次拉取更多的消息。
  4. 监控和告警

    • 使用监控工具,如Prometheus和Grafana,来监控Kafka的积压情况。
    • 设置告警,当积压达到一定阈值时,立即通知相关人员。
  5. 重新分配分区

    • 如果某些分区的消息积压特别严重,可以考虑重新分配分区,使得消费者能够更均匀地处理消息。
  6. 优化生产者速度

    • 如果生产者发送消息的速度过快,导致消费者无法跟上,可以考虑限制生产者的发送速度。
  7. 使用Kafka Streams或KSQL

    • 如果消费者需要进行复杂的流处理,可以考虑使用Kafka Streams或KSQL来分担处理压力。
  8. 数据压缩

    • 使用数据压缩可以减少Kafka中的数据量,从而减轻积压压力。
  9. 清理旧数据

    • 调整Kafka的log.retention.hours参数,定期清理旧的消息,以释放存储空间。
  10. 扩展Kafka集群

  • 如果Kafka集群的资源不足,可以考虑增加更多的broker来分担压力。

总之,解决Kafka的消息积压问题需要综合考虑生产者、消费者和Kafka集群的各个方面,通过监控、调优和扩展来确保消息能够及时被处理。

7 其他方面的能力

7.1 有接触过容器化嘛

容器化是一种技术,它允许将应用程序及其所有依赖项、运行时、系统工具和系统库打包到一个容器中。这个容器可以在任何环境中一致地运行,无论是开发者的本地机器、测试环境还是生产环境。容器化的主要优势在于它提供了一种隔离机制,确保应用程序在不同的环境中都能以相同的方式运行。

容器化的主要特点包括:

  1. 一致性:由于应用程序和所有依赖项都打包在同一个容器中,所以无论容器在哪里运行,它都会表现得一样。

  2. 轻量级:与传统的虚拟机相比,容器不需要完整的操作系统,只需要应用程序和其运行时。这使得容器更加轻量级和快速。

  3. 可移植性:容器可以在任何支持容器技术的环境中运行,无论是物理机、虚拟机还是云环境。

  4. 隔离:每个容器都在其自己的命名空间中运行,与其他容器和主机系统隔离。这提供了安全性和隔离性。

  5. 微服务架构:容器化非常适合微服务架构,因为它允许每个服务在其自己的容器中独立运行。

  6. 快速部署和扩展:容器可以快速启动和停止,这使得部署、扩展和回滚变得更加简单和快速。

Docker是最流行的容器化技术,它提供了一个平台来创建、运行和管理容器。Kubernetes则是一个开源的容器编排工具,用于自动化容器部署、扩展和管理。

总的来说,容器化是一种使应用程序更加一致、可移植和可扩展的技术,它正在改变软件开发和部署的方式。

7.2 你还会其他语言吗

7.3 有接触过ML嘛

7.4 你一般是怎么学习技术的呢

7.5 会写博客嘛

7.6 会读一些开源项目的源码嘛

答:redis,spring线程池都读过

7.7 会介意来合肥嘛

答:

8 反问

8.1 做什么业务呢

答:大模型

8.2 大模型哪方面的

答:大模型后台服务的,工程化的去提供一些周边的生态

8.3 有哪些周边呢

相关推荐
utmhikari4 天前
【架构艺术】服务架构稳定性的基础保障
微服务·架构·稳定性·后端开发·问题排查
utmhikari3 个月前
【架构艺术】大规模业务逻辑迁移实践
重构·架构·数据迁移·稳定性·后端开发
hunter_coder4 个月前
基于Java+SpringBoot+vue+element助农平台设计和实现
数据库·前端开发·后端开发
不打小怪兽4 个月前
Java 基础查漏补缺
java·面试·八股·后端开发·基础知识
小万哥丶5 个月前
Kotlin 数据类型详解:数字、字符、布尔值与类型转换指南
linux·程序人生·面试·程序员·开源·kotlin·移动开发·软件工程·安卓·编程语言·技术·后端开发
小万哥丶5 个月前
Kotlin 变量详解:声明、赋值与最佳实践指南
linux·程序人生·面试·程序员·开源·kotlin·移动开发·软件工程·安卓·编程语言·技术·andriod·后端开发
小万哥丶5 个月前
Kotlin 编程语言详解:特点、应用领域及语法教程
linux·程序人生·面试·程序员·开源·kotlin·移动开发·软件工程·安卓·编程语言·技术·后端开发
小万哥丶5 个月前
NumPy 双曲函数与集合操作详解
linux·python·程序人生·numpy·软件工程·编程语言·后端开发
小万哥丶5 个月前
NumPy 差分、最小公倍数、最大公约数、三角函数详解
linux·python·程序人生·面试·程序员·开源·numpy·软件工程·pip·编程语言·技术·后端开发
小哈里5 个月前
【后端开发】服务开发场景之高性能(CDN与负载均衡,数据库优化,消息队列)
运维·数据库·消息队列·负载均衡·后端开发