2026-7-17-cnblog
一.面式
今天去面式了汉安数智,整体感觉还是不错。
面式遇到的问题:
- sql中in可以用什么来优化;
- 线程锁有哪些;
- 点餐覆盖是什么意思;
- 将一个从前端到后端数据库一个完整的业务应用场景,拿一个模块举例;
- 开发一个项目的操作流程是什么,怎么衔接各个模块的;
- aop具体原理;
- Bean的生命周期,以及如何得到一个实例对象的方式;
- 怎么优化sql,常见的几种方式;
- 有几种索引;
- codex和trae回答为什么会出现乱答现象,也就是出现幻觉,还有什么会影响智能体回答的质量;
回答:
1、in是先执行子查询,再匹配外层,这样会容易出现全表扫描、生成临时表、IO高、效率差,常见优化方案:
- 可以使用exists替代,exists是从外层一行一行在子表中查找,逐行判断是否存在,外层表小,子表大时,exists性能远优于in;比如说user表1000条,order表1000000条,现在场景是查询有过订单的用户,那么如果使用in,就会全表扫描order表,导致性能很差,而如果使用exists,会逐行遍历外层user,查询是否在order表中,因为有主键索引关联,exists效率很高。
- 使用join,数据库可以走高效的索引关联,避免临时表和全扫,是最常用的IN优化手段。
2、线程锁有以下:
- sychronized,也称为内置锁,可以修饰方法和代码块,修饰普通方法针对示例,修饰静态方法针对类,通过阻塞的方式实现。
- ReentrantLock,显式锁,可以手动调用或者关闭;
- 读写锁 ReentrantReadWriteLock,读锁共享,写锁独占,大幅提升读性能,常用于缓存、配置读取。
- 自旋锁,也就是拿不到锁不休眠阻塞,原地空转圈,占用CPU,一直询问直到锁释放,适合持有锁时间短的场景。
- 悲观锁 & 乐观锁(数据库层面),悲观锁:我在操作时,默认别人会修改数据,所以全程上锁,不适合高并发场景;乐观锁:别人不会修改数据,通过版本号机制实现不加锁,适合高并发场景。
- 分段锁,不锁整张表,细化颗粒度,相当于分块,这样适合高并发,比如ConcurrentHashMap,它把整个大集合分成 16个Segment分段,只锁住当前操作的这一个段,所以这也是一个线程安全的集合。
3、点餐覆盖,新下单/改单覆盖原来旧的未结算的订单,覆盖规则就是只能覆盖未支付、未接单、未完成的订单,已经完成的只能走退单、改单流程,保证同一桌、同一用户只有一个有效订单。
4、举最常见的登录模块吧,前端点击登录,通过ajax异步请求发送form表单到后端,请求经过Nginx、全局拦截器,到达后端webMVC的DispatcherServlet前端控制器,拦截到请求后,根据RequestMapping进行路径映射,找到对应处理的controller,在controller中,具体进行登录模块的流程是:
- 首先判断这个用户是否已经认证过,具体是使用jwt组件,生成一个token,可以存入session或者redis中;
- 如果已经认证,那么直接放行;
- 如果没有登录过,那么首先检查是否存在这个用户名,如果不存在,那么返回登录失败;
- 如果存在,那么将密码进行md5哈希,将其与数据库中的密码进行比对,如果不通过,那么登录失败,密码错误;
- 如果通过,那么将认证状态存进session或者redis,返回登录成功;
- 前端拿到返回成功的登录结果后,拿到Token,存入LocalStorage/cookie,后续所有请求都带有这个token,后端拦截器校验登录状态。
5、这是软件工程的核心内容,应该按照以下步骤:
- 需求分析&评审:梳理业务需求,输出原型图、需求文档,确定功能模块,前后端统一接口文档。
- 数据库设计。
- 架构搭建&模块拆分:搭建项目脚手架、统一返回结果、异常处理、全局拦截、工具类,按分层拆分模块,实现低耦合、高内聚。
- 功能迭代开发:按模块逐个开发,接口联调;
- 测试优化:单元测试、接口测试、压力测试、sql优化、代码规范检查、排查bug;
- 部署上线 & 运维监控。
6、aop是面向切面编程,aspect切面。aop底层是依靠反射和动态代理来实现的,可以定义动态代理类,需要在类上加上切面注解@Aspect,通过切入点pointcut注解,注解有一个execution切入表达式参数,这个参数就写需要被代理的方法,这样通过在调用这些方法后,就进行了一个业务增强。依靠反射机制,我们可以获取这个方法的所有信息,可以进行日志保存。通过上面两种方式,实现了在不修改业务代码的情况下,对业务代码进行加强。
7、bean的生命周期指创建到销毁的过程,常见获取bean的4种方式:
-
Autowired和Resource注解;
-
通过Application Context上下文获取;
-
工厂方式获得,适合复杂初始化bean,mybatis整合Spring核心就是利用FactoryBean创建MapperBean;
-
配置类注册,在类上加@Configuration,手动创建Bean返回交给IOC容器管理,适用于第三方类,无法加入Autowired注解这种。
@Configuration public class BeanConfig { // 手动创建Bean并交给Spring容器管理 @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory){ RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(factory); return redisTemplate; } }
8、常见几种方式如下:
- 索引优化:高频查询字段建立索引,遵循最左匹配原则;
- sql语法优化:禁止select *,只查需要字段;大IN改exists和join;避免子查询嵌套过深;分页必须加limit;
- 表结构优化:字段合理设计、避免大字段查询;冷热数据分离;大表分库分表;
- 查询逻辑优化:优先过滤再关联;小表驱动大表;减少多表联查;
- 缓存优化;
9、主键索引、唯一索引、普通索引、联合索引、全文索引,底层都是B+树。
10、我这个主要回答的不是很全面,我主要从大模型获取知识源的方面进行了回答,RAG始终只是一个检索增强生成,是在LLM回答的基础上,先检索知识向量库Milvus,然后进行回答,但是这只是防止幻觉的一个方面。还有其他方面,比如说prompt提示词,显然好的提示词也可以很好的避免大模型出现乱答现象。
幻觉就是模型无依据编造答案、乱答、答非所问,核心原因 + 影响因素如下:
一、产生幻觉的核心原因
- 模型本身概率生成机制:大模型是基于概率预测下一个字,只会通顺、不一定正确,知识盲区会自动编造。
- RAG 检索不准/检索缺失:向量库匹配相似度低、检索不到有效知识,模型只能凭固有知识回答,产生错误。
- 上下文窗口有限:超长对话上下文丢失,信息不全导致乱答。
- 训练数据过时、脏数据:训练数据存在错误、老旧、偏差数据。
二、影响智能体回答质量的所有因素
- Prompt 质量:指令是否清晰、约束是否明确、是否限定回答范围;
- RAG 检索质量:向量分词、向量化模型、召回策略、相似度阈值;
- 上下文对话状态:对话轮次过多、信息遗忘;
- 模型能力:底座模型参数、微调精度;
- 知识库质量:知识是否准确、是否更新、是否去重纠错;
- 后处理机制:是否有答案校验、引用溯源、拒答机制。
AI回答:汉安数智
二、学习方法
在抖音上刷到一个博主艾坤日记,差不多6个月学习时间,完成了Java后端学习,而且还学习agent,我要向他学习,他的学习路线,学习方法。
我看了他几个视频,讲的是现在agent开发岗位除了一些头部大厂,岗位80%的内容还是和传统后端那一套,所以我要保持学习好后端,同时去学习agent。
还是要注重后端的学习,我觉得对于我来说,重要知识点最好自己实现一些,有例子,这样自己掌握更加稳固。
学习完一定要总结,后面我自己也可以使用视频的方式进行记录,说出来总是更好的,我就发布在博客园吧。

浙公网安备 33010602011771号