目录
1、请介绍整个系统后端的架构设计,有哪些模块以及各模块之间的关系?
2、你在项目中是如何设计库表的?可以从字段、索引、关联等方面回答。
3、为什么使用策略模式来封装不同的应用评分算法?它有哪些好处?具体如何实现?
4、你是怎么根据应用来选取要执行的评分算法的?是用 if else 么?
11、你是如何实现一道一道''流式生成题目的,用到了什么算法?
12、什么是 RxJava? 为什么使用 RxJava 来处理流?它有什么优点?
13、什么是 SSE 技术?它有什么优点和不足?适用于哪些场景?
14、为什么用 SSE 技术将生成的题目实时返回给前端?有没有其他实现方案?
16、使用 AI 的过程中,有没有出现不稳定的情况?如果有,你又是如何处理的?
17、你为什么要使用缓存来优化 AI 评分功能?这么做有什么好处?
18、你了解哪些缓存技术?在顶目中又是如何运用缓存的?比如怎么设计缓存?
20、什么是 Redisson? 你在项目中如何使用 Redisson 实现了分布式锁?
23、你为什么使用 Sharding JDBC 技术实现分库分表?它的大致原理是什么?
24、你是如何使用 Sharding JDBC 实现分库分表的?具体怎么分表、用了什么分表算法?
26、有哪些实现幂等设计的方法?你在项目中具体又是怎么实现的?
28、什么是线程池隔离?你在项目中为什么要使用线程池隔离,有什么好处?
30、你的项目支持哪些统计分折功能?后端如何查询出要统计分析的数据?
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 种评分算法,分别是:
- 自定义计算测评类策略
- 自定义计算得分类策略
- 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 客户端实例