AI答题应用平台相关面试题

news2024/11/13 16:32:50

目录

1、请介绍整个系统后端的架构设计,有哪些模块以及各模块之间的关系?

2、你在项目中是如何设计库表的?可以从字段、索引、关联等方面回答。

3、为什么使用策略模式来封装不同的应用评分算法?它有哪些好处?具体如何实现?

4、你是怎么根据应用来选取要执行的评分算法的?是用 if else 么?

5、你的平台支持哪些类型的应用?支持哪些评分算法?

6、如何实现测评类应用的评分算法?请详细讲解。

7、你是怎么快速开发项目后端的,如何避免重复编码?

8、你是怎么实现 AI 生成题目功能的?

9、你是如何封装通用 AI 模块的?提供了哪些方法?

10、如何流式调用 AI 并实时获取到 AI 返回的内容?

11、你是如何实现一道一道''流式生成题目的,用到了什么算法?

12、什么是 RxJava? 为什么使用 RxJava 来处理流?它有什么优点?

13、什么是 SSE 技术?它有什么优点和不足?适用于哪些场景?

14、为什么用 SSE 技术将生成的题目实时返回给前端?有没有其他实现方案?

15、你是怎么实现 AI 评分功能的?

16、使用 AI 的过程中,有没有出现不稳定的情况?如果有,你又是如何处理的?

17、你为什么要使用缓存来优化 AI 评分功能?这么做有什么好处?

18、你了解哪些缓存技术?在顶目中又是如何运用缓存的?比如怎么设计缓存?

19、什么是缓存击穿?你如何解决缓存击穿问题?

20、什么是 Redisson? 你在项目中如何使用 Redisson 实现了分布式锁?

21、什么是分布式锁?使用分布式锁时有些注意事项?

22、什么是分库分表?为什么你要在项目中使用分库分表?

23、你为什么使用 Sharding JDBC 技术实现分库分表?它的大致原理是什么?

24、你是如何使用 Sharding JDBC 实现分库分表的?具体怎么分表、用了什么分表算法?

25、什么是幂等设计?你项目的哪个功能使用了幂等设计?

26、有哪些实现幂等设计的方法?你在项目中具体又是怎么实现的?

27、什么是雪花算法?为什么它能生成分布式全局唯一 id?

28、什么是线程池隔离?你在项目中为什么要使用线程池隔离,有什么好处?

29、你具体怎么实现线程池隔离?怎么设置线程池的参数?

30、你的项目支持哪些统计分折功能?后端如何查询出要统计分析的数据?

31、请介绍一下本项目的完整业务流程?

32、为什么想做这样一个 AI 回答应用平台?

33、为什么要开发 MBTI 性格测试小程序?它和你的答题应用平台有什么联系?

34、你有使用过 AI 工具来辅助编程么?都是如何帮你提高开发效率的?

35、在开发过程中,你遇到过比较复杂的技术问题挑战吗?如果有,请谈谈你是如何解决这些问题的?


1、请介绍整个系统后端的架构设计,有哪些模块以及各模块之间的关系?

整个系统的后端分为:

  • 用户模块:提供登录、用户增删改查等管理功能
  • 应用模块:提供应用增删改查、管理、分享等功能
  • 题目模块:提供题目增删改查、管理等功能
  • 评分模块:提供评分规则定制、答案评分功能
  • 回答模块:提供回答记录查看、管理功能
  • AI 模块:提供 AI 创建题目、AI 智能评分功能

各模块之间的关系如下:

  • 用户登录后,使用应用模块创建应用或者获取应用信息
  • 创建应用需要调用题目模块生成题目或利用 AI 模块生成题目
  • 用户在答题页面根据应用 appId 调用题目模块据得到题目列表,提交答案后调用评分模块,评分模块根据应用的类别执行不同的评分策略,比如自定义评分或调用 AI 模块评分

2、你在项目中是如何设计库表的?可以从字段、索引、关联等方面回答。

根据业务设计用户 / 应用 / 题目 / 评分结果 / 用户答题表。其中题目表采用 JSON 存储复杂的嵌套题目和选项,便于维护扩展,并通过给题目表添加 appId 索引提升检索性能。(感兴趣的同学可以自己测试一下性能的提高比例)

项目中按照业务功能分析,一共设计了用户、应用、题目、评分结果、用户答题五张表。

各表字段统一设置了 createTime、updateTime、isDelete 必备非业务属性字段,便于维护。

根据查询场景,部分表字段还进行了冗余,例如用户答题表需要展示评分结果的名称和描述,因此冗余了评分结果表的 resultName 和 resultDesc 等字段,避免用户查询答题记录时,还需要关联查询评分记录表,提升查询性能。

根据查询场景也做了一些索引设计,例如首页提供通过名称搜索应用功能,因此应用表的 appName 建立了索引。

再比如题目表的获取场景经常需要通过应用 appId 得到题目,因此题目表的 appId 字段也建立了索引。

3、为什么使用策略模式来封装不同的应用评分算法?它有哪些好处?具体如何实现?

因为使用不同评分算法进行判题的业务场景天然适配策略模式。

不同算法对应的就是不同策略,所以使用策略模式来封装了评分算法,便于维护和扩展。

具体实现方式:

1)定义 ScoringStrategy 接口,约束了评分的入参和出参。

2)定义 ScoringStrategyConfig 注解,一共有 appType 和 scoringStrategy 两个属性标识了策略对应的应用属性和评分类型。

3)每种评分算法都实现 ScoringStrategy 接口,且标注对应的 ScoringStrategyConfig 注解。

4)定义 ScoringStrategyExecutor 方法作为驱动类,内部利用 Spring 注入了 ScoringStrategy 实现类列表,得到所有评分算法。定义了 execute 方法,遍历评分算法列表,通过反射获取策略实现类注解上的属性即可筛选出对应的评分算法。

4、你是怎么根据应用来选取要执行的评分算法的?是用 if else 么?

核心实现是注解。

一开始我想的是 if else ,但是根据 开闭原则,后面要添加新的评分算法需要修改 if else 的代码,因此我想到了 Spring 自动注入 + 自定义注解来实现自动选取评分算法。

具体来说,所有评分算法都实现了同一个策略接口,Spring 可以自动注入这些实现类,根据注解上定义的 appType 和 socringStrategy,就可以从这些实现类中筛选出要执行的评分算法。

5、你的平台支持哪些类型的应用?支持哪些评分算法?

平台现在支持得分类应用和测评类两种应用类型。

一共支持 3 种评分算法,分别是:

  1. 自定义计算测评类策略
  2. 自定义计算得分类策略
  3. AI 分析测评类策略

6、如何实现测评类应用的评分算法?请详细讲解。

1)测评类每道题对应的答案都设置了属性,以 MBTI 为例,内向的答案对应 I 属性,外向的答案对应 E 属性。

2)根据用户选择的答案计算出对应属性总数量,例如 I 为 10 个、E 为 2 个、J 为 10 个、P 为 2 个,将其构建成一个属性得分 map,key 为属性值、value 为累计数量。

示例 Map 结构如下:

{
  I: 10,
  E: 2,
  J: 10,
  P: 2
}

3)评分结果表的结果也设置了对应的属性,例如 ISTJ 包含了 I、S、T、J 这四个属性,ESTJ 则包含了 E、S、T、J 。对于每种评分结果,遍历属性集合,从上述 Map 结构中获取到属性对应的评分。

比如 ISTJ 评分结果对应的得分为:10 (I) + 0 (S) + 0 (T) + 10 (J) = 20 分

4)遍历所有评分结果,使用上述算法计算得分,最终获取到得分最高的评分结果。

通过定义 Map 的方式,拿空间换时间,减少了算法复杂度,提高了算法的执行效率。

7、你是怎么快速开发项目后端的,如何避免重复编码?

总结来说利用了:项目模板 + MyBatisX 插件 + 自定义代码生成器 + AI。

1)首先我基于后端通用项目模板进行开发(相当于项目的 initializr),该模板内置了很多后端开发常用的能力,如全局异常处理器、通用响应对象包装、整合了数据库和 Redis 等,避免重复工作。

非常熟悉后端通用项目模板的同学,也可以说基于自己开发的模板二次开发。

2)在我设计完库表后,利用 IDEA 的 MybatisX 插件生成对应的实体类、Mapper 等文件。

3)再利用自定义代码生成器,根据实体名称等信息生成了包含增删改查等通用功能的 Controller、Service 等文件。该生成器基于 FreeMarker 模板引擎实现。

4)现在 AI 工具能力已经很强了,在编码的过程中,也使用 AI 插件生成了一些代码,比如测试数据。

8、你是怎么实现 AI 生成题目功能的?

1 ) AI 生成题目基础功能实现:通过编写 Prompt 实现让 AI 返回 JSON 格式的题目内容。并通过系统预设、少样本学习、任务拆解等技巧优化 Prompt 、通过 AI 开放平台界面调试 Prompt, 提高 AI 生成内容的完善度和准确度。

2 )流式优化:基于 AI 生成题目较慢,选用 ChatGLM AI 的流式 API 开通过 SSE 实时推送单道题目给前端,提高用户体验。

3 )具体实现:在 AI 平台没有完整返回单题目对应的字符时,不应该返回给前端。为了拼接单道题目,我基于 RxJava 的操作符链式调用处理 AI 异步数据流,先通过 map 获取并处理字符串(过滤持殊字符如 '\n') 、 filter 过滤空值、 fIatMap 映射字符串为个字符,再通过括号平衡算法准确拼出单道题目,使得逻辑简单清晰。

9、你是如何封装通用 AI 模块的?提供了哪些方法?

1 )基于智谱 SDK 实现 AI 调用大模型的能力

2 )通过创建配置类,顶目启动时自动读取配置文件中的秘钥来初始化 AI 客户端实例

3 )编写 Manager Bean 来调用 AI 客户端,提供了多种对 AI 的请求封装方法,并提供了统一的异常处理能力。

比如随机性低的同步调用 AI 、随机性高的流式调用、简化消息传参的方法等。

10、如何流式调用 AI 并实时获取到 AI 返回的内容?

ChatGLM 的 AI SDK 提供了流式调用的能力,我自主封装了 AI Manager 简化 AI 流式调用的传参,返回值是 Flowable 响应式对象。我利用 RxJava 框架来处理 AI 实时返回的 Stream 流数据,将 AI 返回的字符生成结果拼接成“一道一道"题目,通过 SSE 实时准送给前端。

11、你是如何实现一道一道''流式生成题目的,用到了什么算法?

首先流式调用 AI 接囗,利用 RxJava 的操作符链式调用处理 AI 实时返回的异步数据流。先通过 map 获取并处理字符串(过滤待殊字符如 '\n') 、 filter 过滤空值、 flatMap 映射字符串为单个字符,再通过括号平衡算法准确拼接出单道题目,便得逻辑简单清晰。括号平衡算法的解释因为每道颗目是 JSON 结构,左括号数一定等于右括号数。所以可以遍历当前字符串,用一个计数器统计括号数量出现一次左括号则计数加一,出现一次右括号则计数减一,当计数为零时,说明完整的一道题已返回完毕,此时通过 SSE 返回给前端。

12、什么是 RxJava? 为什么使用 RxJava 来处理流?它有什么优点?

RxJava 是一个基于事件驱动的、利用可观测序列来实现异步编程的类库,是响应式编程在 Java 语言上的实现。

1 )它提供了响应式编程模型,使得代码更具可读性。比如 doOnNext 、 doOnError。

2 )提供了丰富的操作符,简化异步操作事件、处理数据转化等。比如 map 、 filter、 flatMap 。

3 )简化线程管理,可以很容易地在不同线程中进行数据流的处理。比如 0bserveOn 、 subscribeOn。

它的一个核心应用场景就是 UI 场景,像 Android 开发都会用到 RxJava。 UI 场景天然涉及到响应和事件这两点,比如我们在手机 app 上点击某按钮,对应 app 就会弹出某个界面,点击按钮其实就是一个事件,那么弹出界面就是对应的响应。

13、什么是 SSE 技术?它有什么优点和不足?适用于哪些场景?

SSE 服务器发送事件 (Server-Sent Events) 是一种用于从服务器到客户端的单向、实时数据传输技术,基于 HTTP 协议实现。

它有几个重要的特点:

  1. 单向通信: SSE 只支持服务器向客户端的单向通信,客户端不能向服务器发送数据。
  2. 文本格式: SSE 使用纯文本格式传输数据,使用 HTTP 响应的 text/event-stream MIME 类型。
  3. 保持连接: SSE 通过保持一个持久的 HTTP 连接,实现服务器向客户端推送更新,而不需要客户端频繁轮询。
  4. 自动重连:如果连接中断,浏览器会自动尝试重新连接,确保数据流的连续性。

它的优点:

  1. 简单易用: SSE 在实现上相对简单,无需复杂的配置和建立连接过程。
  2. 实时性:可以实现服务器向客户端的实时数据推送,使得客户端能够及时获得更新。
  3. 标准化:基于标准的 HTTP 协议,因此具有广泛的浏览器支持。
  4. 无需握手机制:与其他技术(如 WebSocket) 相比, SSE 不需要握手机制,可以降低连接的延迟。

不足:

  1. 单向通信: SSE 是服务器向客户端的单向通信模式,客户端无法向服务器发送数据。
  2. 连接维持: SSE 需要保持持续连接,可能会造成服务器资源占用。

适用场景:

  1. 实时更新:股票价格、体育比赛比分、新闻更新等需要实时推送的应用。
  2. 日志监控:实时监控服务器日志或应用状态。
  3. 通知系统:向客户端推送系统通知或消息
  4. AI 对话:见 AI 模型页面对话。

14、为什么用 SSE 技术将生成的题目实时返回给前端?有没有其他实现方案?

SSE 具有如下优点:

  1. 简单易用: SSE 在实现上相对简单,无需复杂的配置和建立连接过程。
  2. 实时性:可以实现服务器向客户端的实时数据推送,使得客户端能够及时获得更新。
  3. 标准化:基于标准的 HTTP 协议,因此具有广泛的浏览器支持。

4. 无需握手机制:与其他技术(如 WebSocket) 相比, SSE 不需要握手机制,可以降低连接的延迟。

其他实现方案:

  1. 轮询(前端主动去要数据)

前端间隔一定时间就调用后端提供的结果接囗,比如 200ms 一次,后端处理一些结果就累加放置在缓存中。

  1. WebSocket

全双工协议,前端能实时推送数据给后端(或者从后端缓存拿数据)后端也可以实时推送数据给前端。

15、你是怎么实现 AI 评分功能的?

  1. ChatGLM 的 AI SDK 提供了流式调用的能力,我自主封装了 AI Manager 简化 AI 调用的传参和编码。
  2. 获取需要提供给 AI 的参数列表,包括应用信息、题目信息和用户答案。但是需要注意,题目数量可能会很多,如果将完整的题目结构(包括选顶列表)输入给 AI, 可能会超出最大 token 限制,所以可以进行优化只保留用户选顶对应的答案。示例结构如下:
{
  "appName": "MBTI 性格测试",
  "appDesc": "测试你的 MBTI 性格",
  "question": [
    {
      "title": "你喜欢和人交流",
      "answer": "喜欢"
    }
  ]
}
  1. 利用上述参数来编写 Prompt ,让 AI 返回 JSON 格式的评分结果名称和详细描述。
  2. 调用 AI 并保存评分结果到数据库中,返回给前端用户即可。

16、使用 AI 的过程中,有没有出现不稳定的情况?如果有,你又是如何处理的?

我遇到了几种不稳定的情况:

  1. AI 没有按照要求返回 JSON 数据,有时额外返回了内容。我通过优化 Prompt (比如给 AI 示例样本结果)和对 AI 结果进行字符串截取处理,提高了稳定性。
  2. 由于网络原因导致调用 AI 平台失败。我通过 Guava Retrying 库实现了失败后的自动重试逻辑,且最大重试 3 次。
  3. AI 调用余额不足。我通过编写定时任务定期查询剩余额度,如果额度不足。会提前通过邮件(或者其他方式)进行告警;并且如果用户便用时余额不足,会给一个友好提示。

第 2 、3种惜况要自主实现,也并不难。

17、你为什么要使用缓存来优化 AI 评分功能?这么做有什么好处?

之前的 AI 评分功能存在 2 个问题:

  1. AI 调用需要费用,如果用户对同样的题目做出同样的选择理论会得到一样的解答,不要每次都询问 AI, 存在资源的浪费。
  2. AI 评分的响应时间较长,效率有待提升。

考虑到“减少响应时长" 和 "数据复用" 我选择缓存技术来优化 AI 评分功能。出于项目前期采用单机部署,所以选用了成本相对较低的 Caffeine 本地缓存来缓存用户笞案 Hash 对应的 AI 评分结果,提高评分性能 (10S 到 5ms) 的同时大幅节约成本;开通过 Redisson 分布式锁解决缓存击穿问题。

18、你了解哪些缓存技术?在顶目中又是如何运用缓存的?比如怎么设计缓存?

有哪些缓存技术?

缓存技术在项目中一般可以分为两种:本地缓存和分布式缓存。

  1. 本地缓存可以便用哈希表 Ehcachev Caffeine 等实现。
  2. 分布式缓存可以便用 Rediss Memcached 等实现。

项目中如何运用缓存?怎么设计?

对于我的项目,由于不考虑分布式或扩容、且不要求持久化、不用保证多台机器缓存间的一致性,所以选择成本低的本地缓存 Caffeine 来实现。

  1. 缓存 key 设计

回归到需求“用户对同样的题目做出同样的选择,理论会得到一样的解答,所以可以将应用 id 和用户的答案列表作为 key。但答案列表可能很长,可以利用哈希算法 (md5) 来压缩 key, 节省空间。注意如果是分布式缓存,还需要在 key 开头拼接业务前缀。此处我们可以单独为每个业务创建本地缓存,相互隔离,所以 key 可以简单一些。

  1. 缓存 value 设计

缓存 AI 回答的结果,为了可读性可以存 JSON 结构,为了压缩空间可以存二进制等其他结构。

  1. 缓存过期时间设置

假设有 20 道题目,那么不同选择累计总次数一共是 2 的 20 次方, 100 多万。过期时间根据实际业务场景和缓存空间的大小、数据的一致性的要求设置,台适即可,此处设置为 1 天。

  1. 业务流程

在 AI 回答前,哈希处理用户答题选择,得到摘要,拼接缓存 key。通过摘要查找缓存,若命中则直接返回答题结果。若缓存中未找到,则请求 AI 回答。正确解析 AI 返回的 JSON 后,将其放置在缓存中。

  1. 缓存相关问题的解决

还需要注意缓存过期后的处理,防止产生缓存击穿、雪崩等问题。我在项目中通过 Redisson 分布式锁解决了缓存击穿。

19、什么是缓存击穿?你如何解决缓存击穿问题?

  1. 什么是缓存击穿?

缓存击穿是指在高并发的情况下,针对一个不存在于缓存中但是访问量很高的 key, 每次请求都要去数据库查询,导致数据库压力过大,性能下降的情况。当某个热点 key 的缓存过期时,大量请求同时访问这个 key, 由于缓存为空,导数所有请求直接访问数据库,引起数据库压力骤增。

对于本顶目,多个用户同时提交答案交给 AI 测评时,如果缓存过期,那么会有大量同时调用 AI 接囗的并发请求,导致被 AI 服务器限制。

  1. 如何解决缓存击穿问题?

常见解决缓存击穿思路:

1 .设置热点缓存数据永不过期,并且提前预热。2 .缓存不存在时,通过加锁让操作串行执行,并设置缓存。3 .定时更新热点数据的缓存。

我选择第二种方案--加锁。如果服务部署在多个机器上,就必须要使用分布式锁。分布式锁的实现细节很多,所以我直接使用 Redisson 实现分布式锁。 Redisson 为 Redis 提供了多种数据结构的支持,提供了线程安全的操作,简化了在 Java 中使用 Redis 的复杂度。

20、什么是 Redisson? 你在项目中如何使用 Redisson 实现了分布式锁?

  1. 什么是 Redisson?

Redisson 是一个基于 Redis 的 Java 调用类库,提供了丰富的分布式对象和服务,其中包括分布式锁、分布式集合、分布式对象等功能。主要为了简化 Java 开发人员在分布式环境中便用 Redis 的复杂性,提供了易于使用的 API 以及各种分布式实现。

  1. Redisson 如何实现分布式锁?

编写配置类,从配置文件中读取 Redis 配置并初始化 Redisson 客户端 Bean;通过 Redisson 客户端的 getLock("myLock") 方法获取分布式锁;通过 tryLock 方法尝试获得锁,并设置抢锁等待时间(3秒)和超时释放时间( 15 秒);利用 try.. .finally... 保证执行操作结束后,锁会被当前线程释放。

21、什么是分布式锁?使用分布式锁时有些注意事项?

分布式锁是在分布式系统中用于控制对共享资源或临界区的访问的一种锁机制。它可以确保在多个节点或实例上同一时间只有一个进程能够获取锁,,从而保证数据的一致性和避免并发访问下的数据竞争和冲突。

注意事顶如下:

  1. 需要合理设置超时释放时间,避免造成死锁。
  2. 业务处理完毕后及时释放锁,防止业务阻塞。
  3. 必须由当前线程释放锁,不能释放其他线程加的锁,防止业务执行受到影响。
  4. 合理设置抢锁等待时间,避免长时间无效等待。
  5. 可以利用看门狗机制实现锁的续期,防止由于业务处理时间大于锁超时释放时间,导数一把锁被多个线程拥有,从而出现错误。

22、什么是分库分表?为什么你要在项目中使用分库分表?

  1. 什么是分库分表?

分库分表是指将一个数据库按照一定规则分成多个库(分库),或将一个表按照一定规则分成多个表(分表)的数据库架构设计方法。通常在数据量大、访问频繁的业务系统中会采用分库分表的方式来提高数据库的性能、可扩展性、可用性。

  1. 为什么要在项目中使用分库分表?

如果我们的平台发展迅速,用户量激增,用户提交的答案数也会越来越多。从数据库层面去思考,用户答题记录表可能会比较庞大,查询的性能也会下降。因为数据越多,底层存储的 B+ 树就越高,树越高则查询的次数就越多,那么性能也就越差。因此我选择应用的 appld 作为分片键,运用取模算法,对用户答题记录表进行分表,分为了 2 张表。其实这里也是出于学习的目的,实践了下 Sharding JDBC 框架。

23、你为什么使用 Sharding JDBC 技术实现分库分表?它的大致原理是什么?

因为 Sharding JDBC 是 Apache 旗下的开源顶目,生态好、社区活跃、简单易用、容易上手。

它的大致原理可以用几个字总结:改写 SQL。

比如我们想根据 appld 来将对应的用户答题记录表进行分表。将 appld % 2 等于 0 的应用的所有用户的答题记都划分到 user_answer_0, 等于 1 的应用的所有用户的答题记录都划分到 user_answer_1。按照我们正常的想法处理逻辑就是:

if(appId % 2 == 0){
	userAnswer0Service.save(userAnswer);
} else {
	userAnswer1Service.save(userAnswer);
}

而用了 Sharding-JDBC 后,我们只要写好配置 Sharding-JDBC 就会根据配置执行我们上面的逻辑,在业务代码上我们就可以透明化分库分表的存在,减少了很多重复逻辑!它会解析 SQL ,根据我们指定的分片键,按照我们设置的分片策略来计算得到对应的路由分片(数据库或者表)最终改写 SQL 后进行 SQL 的执行。

24、你是如何使用 Sharding JDBC 实现分库分表的?具体怎么分表、用了什么分表算法?

Sharding JDBC 开箱即用,只要在配置文件中填写好数据源信息、分片算法、分表依赖的列等,就能自动实现业务透明的分库分表。本项目中,我对数据增长较快的用户答题记录表进行分表,选择应用 appld 作为分表键,采用取模分片算法,将用户答题记表拆分为 2 个表 (user-answer-o 和 user-answer-l ),提高了单表查询性能和可扩展性。(感兴趣的同学可以自己测试一下百万行数据的性能提高比例)

25、什么是幂等设计?你项目的哪个功能使用了幂等设计?

幂等设计在编程场景指的是:使用相同参数多次调用同一接囗,产生的结果或影响和单次调用是一致的。为防止用户多次提交重复答案,基于雪花算法为每次答题分配唯一 id ,开通过数据库主键实现幂等设计,避免了重复的脏数据。

26、有哪些实现幂等设计的方法?你在项目中具体又是怎么实现的?

有 4 种常用的幂等设计方法:

  1. 利用数据库唯一索引的一致性保证幂等性
  2. 利用乐观锁在某些场景下也能实现幂等性
  3. 一些天然的幂等操作比如 delete 操作(因为删除一次和多次都是一样的)
  4. 利用分布式锁防止并发,通过逻辑判断可以实现幂等性

在项目中为防止用户多次提交重复答案,后端基于雪花算法为每次答题分配唯一 id, 并且在用户进入答题页时返回给前端。用户提交答案时会带该 id ,利用数据库主键可以防止重复 id 数据的插入,如果 id 重复会抛出 Du pIicateKeyException 异常,直接忽略即可。这样就避免了重复的脏数据。

27、什么是雪花算法?为什么它能生成分布式全局唯一 id?

雪花算法 (Snowflake Algorithm) 是一种用来生成分布式系统中全局唯一的 ID 的算法。由 Twitter 开发的,用于满足分布式系统中生成唯一 ID 的需求。

雪花算法生成的唯一 ID 通常是一个 64 位的整数,按照以下结构组成:

  1. 首位符号位(固定为 0 ):符号位始終为 0 ,保证生成的是正整数。
  2. 41 位时间戳(毫秒级):表示生成的的时间,可以支持约69年的时间范围。
  3. 10 位机器标识(分布式部署时的机器 ID) :可以支持 1024 台不同的机器。
  4. 12 位序列号(同一机器同一毫秒内的自增序列):表示同一台机器同一毫秒内生成的不同 ID 的序列号。

雪花算法原理图如下:

雪花算法能生成分布式全局唯一 ID 的原因:

  1. 雪花算法允许在同一毫秒内生成多个不同的 ID, 通过序列号的自增保证在高并发情况下生成的 ID 唯一性。
  2. 通过机器部分的标识符保证了在不同的机器上生成 ID 时不会发生冲突。
  3. 利用时间戳部分的信息,确保生成的 ID 按时间递增,可以方便地对 ID 进行排序和分析。

28、什么是线程池隔离?你在项目中为什么要使用线程池隔离,有什么好处?

什么是线程池隔离?

线程池隔离是一种通过为不同的任务类型或者不同的资源分配独立的线程池来隔离不同类型的任务或资源的执行的机制。这种机制可以有效地控制各种任务之间的相互影响,提高系统的稳定性和可靠性。

项目中为什么要使用线程池隔离,有什么好处?

如果所有业务操作都使用一个线程池,最大的问题就是相互影响。所以,在一些业务敏感的场景,需要隔离线程池,它有以下几点好处:

  1. 故障隔离,缩小事故范围。
  2. 资源隔离,防止业务之间抢占资源。同时支持更精细化地管理资源,比如不重要的场景给小一点的线程池,核心场景配置大线程池。
  3. 性能优化,一些业务场景的任务是 CPU 密集型,一些是 I/ 0 密集型,不同任务类型要配置不同的线程池。

回到本项目,因为服务器资源有限,对于 AI 批量生成题目功能,我为会员创建了核心线程数更大的隔离线程池,尽量保证普通用户的操作不会影晌到会员使用的体验。

29、你具体怎么实现线程池隔离?怎么设置线程池的参数?

怎么实现线程池隔离?

我针对普通用户和会员用户定制了两个不同的线程池,使用处理响应式数据流时,可以通过 observeOn(scheduler) 方法,根据用户的身份指定使用的线程池。

怎么设置线程池的参数?

普通用户线程池:核心线程数和最大线程数都为 1 ,即单线程,任务队列长度为 1000 ,超过则拒绝提交。这样可以有效限制普通用户调用 AI 的频率。

会员用户线程池:核心线程数为 10 ,最大线程数为 20 ,任务队列长度为 5000 ,超过则拒绝提交。即允许更多会员同时使用 AI 。

我还通过编写单元测试,验证了线程池隔离的有效性。

30、你的项目支持哪些统计分折功能?后端如何查询出要统计分析的数据?

项目支持哪些统计分析功能?

支持 2 种统计分析功能:热门应用排行统计和应用回答分布统计。

作用分别是:

  1. 热门应用排行统计:在 AI 答题应用平台中,我们可以分析哪个 App 用户使用的最多,后期功能迭代时,可根据统计结果,把热门的应用排在首页的靠前位置,并且添加缓存以提升访问速度。
  2. 应用回答分布统计:根据用户测评结果的分布情况,可优先对群体大的用户进行定制化开发或广告投放,吸引更多用户。

后端如何查询出要统计分析的数据?

编写 SQL 语句,通过 group by 聚合语法实现对数据的分组统计。在 Java 程序中,通过 MyBatis 的自定义 SQL 注解实现(如 @SeIect) 复杂 SQL 语句的执行。

后端查出数据后,前端可以通过 ECharts 实现可视化。

31、请介绍一下本项目的完整业务流程?

本项目一共有三类用户角色,分别是:应用创建者、应用使用者、管理员。

应用创建者可以创建自定义应用,依次填写应用基本信息(名称描述等)、题目和选项、以及不同选顶对应的评分结果。支持选择得分类和测评类这 2 种应用类型,支持选择自定义评分或 AI 评分这 2 种评分算法。管理者负责审核应用创建者申请的自定义应用,含上下架应用和分析应用等管理功能。此外,管理员也可以针对本站的各类数据进行管理比如用户的回答结果。应用使用者可以在首页搜索和挑选应用进行笞题,提交答案后得到评分结果。注意,应用使用者也可以创建应用,应用创建者也可以参与应用答题,二者的身份不做明确的区分。

32、为什么想做这样一个 AI 回答应用平台?

起初在网上看到 MBTI 性格测试应用还要收费,觉得开发这样一个答题应用并不难,就打算自己做一个。但后面转念一想,既然能开发一个答题应用为什么不能开发多个答题应用呢?毕竟题目结构和答题流程都是一致的,也不要太多的额外开发成本,还能够动态维护题目数据,而不是在前端硬编码。而且现在 AI 越来越流行就想看用 AI 提高创建应用生成题目的效率、且让 AI 给用户的回答评分从而提高回答的丰富度,不用自己去网上翻别人的答案了。

33、为什么要开发 MBTI 性格测试小程序?它和你的答题应用平台有什么联系?

MBTI 小程序只是 AI 答题应用平台的一个实例 Demo ,我做它主要有几个理由:

  1. 通过这个小项目确定了题目结构、跑通了答题功能的业务流程,为后续开发平台打下了基础
  2. 网上有很多收费的 MBTI 性格测试,所以我选择做这个主题的小程序,比较实用有趣。
  3. 这个小程序开发比较简单,我也借此学习了跨端小程序的开发框架和小程序开发流程。

后续还可以优化完善小程序,将前端硬编码题目数据改造为调用平台的后端接囗根据 appld 动态获取题目数据,从而让小程序支持切换多种不同的答题应用。

34、你有使用过 AI 工具来辅助编程么?都是如何帮你提高开发效率的?

必须的,我使用的是国内的免费 AI 编程助手 CodeGeex, 主要便用了下列功能:

·自动生成单元测试

·自动给代码补充注释

·解释分析代码,帮助我理解一些类库的源码

·示例数据生成帮助我快速构造了一些模拟数据

·代码补全,帮我提高了编码效率

·代码生成,帮我生成一些简单的算法

35、在开发过程中,你遇到过比较复杂的技术问题挑战吗?如果有,请谈谈你是如何解决这些问题的?

可以从以上任意一道主观的面试题出发去讲,比如你是怎么实现 AI 生成题目功能并使用 SSE + RxJava 进行优化的?如果准确地根据实时字符流拼接出一道完整的题目并立即返回给前端?如何一步步封装了通用的 AI 模块?发现有多种评分算法 (if else) 时,便用策略模式优化代码;发现用户可能同时提交多个重复回答时,采用幂等设计并通过缓存防止 AI 资源的浪费。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1977310.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Elasticsearch 的DSL查询,聚合查询与多维度数据统计

文章目录 搜索聚合高阶概念 搜索 即从一个索引下按照特定的字段或关键词搜索出符合用户预期的一个或者一堆cocument,然后根据文档的相关度得分,在返回的结果集里并根据得分对这些文档进行一定的排序。 聚合 根据业务需求,对文档中的某个或…

【源码+文档+调试讲解】营业厅宽带系统设计与实现

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本营业厅宽带系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息&…

Action部署在线上写文章

原文:https://blog.c12th.cn/archives/32.html 前言 之前分别出了 Hexo 和 Hugo 的 Action搭建教程,相当于伪动态,可以在线上写文章了;不过对于喜欢魔改的同学就不太友好了qwq 教程 github.dev 确保在配置过程中能访问Github &…

学工系统学生家庭情况登记功能概述

智慧校园学工系统中的“学生家庭情况”模块主要用于收集和管理学生的家庭背景信息,以便学校更好地了解学生的情况,并据此提供相应的支持和服务。该模块通常包括以下几个方面: 基本信息录入:支持录入学生的家庭成员信息&#xff0c…

ocaml精解【1】

文章目录 概述简介一、基本概述二、开发工具三、语言特性四、应用场景五、未来展望 windows下安装基础 参考文献 概述 简介 OCaml(Objective Caml)是Caml编程语言的主要实现,由Xavier Leroy、Jrme Vouillon、Damien Doligez、Didier Rmy等人…

一款免费强大的电脑锁屏工具,中文绿色免安装

这款软件主要特点是锁屏后不显示密码输入框,直接输入密码即可解锁。 ScreenBlur是一款功能强大的电脑屏幕锁软件,主要用于保护用户的隐私和数据安全。该软件的主要功能包括自动锁屏、隐藏桌面、加密锁机等。 功能特点 自动锁屏:用户可以设…

C语言之unsigned long long与struct相互转换实例(五十六)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 新书发布:《Android系统多媒体进阶实战》🚀 优质专栏: Audio工程师进阶系列…

数学希腊符号

1、Α α alpha /a:lf/ 阿尔法 2、Β β beta /bet/ 贝塔 3、Γ γ gamma /ga:m/ 伽马 4、Δ δ delta /delt/ 德尔塔 5、Ε ε epsilon /epsilon/ 伊普西龙 6、Ζ ζ zeta /zat/ 截塔 7、Η η eta /eit/ 艾塔 8、Θ θ thet /θit/ 西塔 9、Ι ι iot /aiot/ 约塔 10、Κ κ …

ADHD儿童康复的灯塔,专业与爱共筑希望之桥

在自闭症及注意缺陷多动障碍(ADHD)儿童教育领域,专业的康复学校扮演着至关重要的角色。这些学校不仅为孩子们提供科学的康复训练,还致力于帮助他们融入社会,实现自我价值。 以星启帆自闭症儿童康复机构为例&#xff0c…

【系统架构设计师】二十四、安全架构设计理论与实践③

目录 五、网络安全体系架构设计 5.1 OSI安全架构 5.2 认证框架 5.3 访问控制框架 5.4 机密性框架 5.5 完整性框架 5.6 抗抵赖框架 往期推荐 五、网络安全体系架构设计 5.1 OSI安全架构 OSI定义了7层协议,其中除第5层(会话层)外,每一层均能提供相…

NetAssist免费下载使用

这种TCPUDP的局域网工具有很多,但是找起来很麻烦,在微信小程序里面发现了一个“TCPUDP局域网小助手”的工具,打开即用非常方便, 打开之后长这样 能下载电脑端NetAssist

使用RK Docker环境编译RK SDK

文章目录 前言Docker介绍实验环境获取RK Docker镜像加载RK Docker镜像使用RK Docker环境编译SDK其它 前言 作为一名嵌入式Linux的学习者,目前编译各种平台,用的都是同一个编译机(Ubuntu虚拟机)。之前一直在折腾全志,所…

GraphRag本地测试

测试环境:win10 python3.11.9 graphRAG的安装还是很简单的,直接pip pip install graphrag 但要注意,官方说了需要 python3.10-3.12 安装完成后,建立一个文件夹,存放你的知识数据,目前graphRAG仅支持txt和…

Mysql错误:InnoDB: page_cleaner

今天一大早就收到同事昨晚发过来的信息:某省份的充电桩在昨晚22点到23点期间大量挂单即充电不能结算。首先想到的就是订单服务挂了,可查了数据一切正常。所以继续早跑,等上班回公司再查查原因。 来到公司查看了昨晚的项目日记情况&#xff0c…

使用Markdown画图

大部分 Markdown 编辑器的画图功能都是基于 mermaid 的,因此我们先介绍下它。 ‍ 什么是 mermaid ​ ‍ mermaid 是一个开源的项目,旨在通过纯文本的形式来画图,支持流程图,时序图,甘特图,类图&#x…

Arduino PID库 (1)– 简介

Arduino PID库 (1)– 简介 pid内容索引-CSDN博客pid术语及整定原则参考:手把手教你看懂并理解Arduino PID控制库——引子)库的改进QuickPID-sTune库 原文地址 随着新的Arduino PID库的发布,最后一个库虽然很可靠,但…

浅谈AC自动机算法(c++)

文章目录 自动机一些简单的自动机: AC 自动机字典树构建失配指针构建指针 [HNOI2006] 最短母串问题题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示思路AC代码 「一本通 2.4 例 1」Keywords SearchAC代码 自动机 自动机是什么? 自动机的作…

Linux小组件:gcc

gcc 是C语言的编译器,在Linux下我们也用这个编译C语言 安装gcc sudo apt install build-essential 查看gcc版本信息 gcc --version 有时候会出现代码编译不过去的问题,通常可能是gcc的编译标准太低,不支持某些写法 比如在很多旧的编译标…

rk3588 部署yolov8.rknn

本文从步骤来记录在rk3588芯片上部署yolov8模型 主机:windows10 VMware Workstation 16 Pro 硬件:RK3588 EVB板 模型: RK3588.rknn 软件开发环境: c cmake step1: 主机上执行: 将rknn_model_zoo 工程文件下载…

spring:标签property

标签property对应于bean类公开的JavaBean setter方法。标签property的属性中,name为属性名,type为“”引号里面的类型,use为是否必须出现。 1.ref引用一个已经存在的对象,value创建一个新的对象 2.value可以赋一些简单类型的值,…