2026-7-17-cnblog

一.面式

今天去面式了汉安数智,整体感觉还是不错。

面式遇到的问题:

  1. sql中in可以用什么来优化;
  2. 线程锁有哪些;
  3. 点餐覆盖是什么意思;
  4. 将一个从前端到后端数据库一个完整的业务应用场景,拿一个模块举例;
  5. 开发一个项目的操作流程是什么,怎么衔接各个模块的;
  6. aop具体原理;
  7. Bean的生命周期,以及如何得到一个实例对象的方式;
  8. 怎么优化sql,常见的几种方式;
  9. 有几种索引;
  10. codex和trae回答为什么会出现乱答现象,也就是出现幻觉,还有什么会影响智能体回答的质量;

回答:

1、in是先执行子查询,再匹配外层,这样会容易出现全表扫描、生成临时表、IO高、效率差,常见优化方案:

  • 可以使用exists替代,exists是从外层一行一行在子表中查找,逐行判断是否存在,外层表小,子表大时,exists性能远优于in;比如说user表1000条,order表1000000条,现在场景是查询有过订单的用户,那么如果使用in,就会全表扫描order表,导致性能很差,而如果使用exists,会逐行遍历外层user,查询是否在order表中,因为有主键索引关联,exists效率很高。
  • 使用join,数据库可以走高效的索引关联,避免临时表和全扫,是最常用的IN优化手段。

2、线程锁有以下:

  1. sychronized,也称为内置锁,可以修饰方法和代码块,修饰普通方法针对示例,修饰静态方法针对类,通过阻塞的方式实现。
  2. ReentrantLock,显式锁,可以手动调用或者关闭;
  3. 读写锁 ReentrantReadWriteLock,读锁共享,写锁独占,大幅提升读性能,常用于缓存、配置读取。
  4. 自旋锁,也就是拿不到锁不休眠阻塞,原地空转圈,占用CPU,一直询问直到锁释放,适合持有锁时间短的场景。
  5. 悲观锁 & 乐观锁(数据库层面),悲观锁:我在操作时,默认别人会修改数据,所以全程上锁,不适合高并发场景;乐观锁:别人不会修改数据,通过版本号机制实现不加锁,适合高并发场景。
  6. 分段锁,不锁整张表,细化颗粒度,相当于分块,这样适合高并发,比如ConcurrentHashMap,它把整个大集合分成 16个Segment分段,只锁住当前操作的这一个段,所以这也是一个线程安全的集合。

3、点餐覆盖,新下单/改单覆盖原来旧的未结算的订单,覆盖规则就是只能覆盖未支付、未接单、未完成的订单,已经完成的只能走退单、改单流程,保证同一桌、同一用户只有一个有效订单。

4、举最常见的登录模块吧,前端点击登录,通过ajax异步请求发送form表单到后端,请求经过Nginx、全局拦截器,到达后端webMVC的DispatcherServlet前端控制器,拦截到请求后,根据RequestMapping进行路径映射,找到对应处理的controller,在controller中,具体进行登录模块的流程是:

  1. 首先判断这个用户是否已经认证过,具体是使用jwt组件,生成一个token,可以存入session或者redis中;
  2. 如果已经认证,那么直接放行;
  3. 如果没有登录过,那么首先检查是否存在这个用户名,如果不存在,那么返回登录失败;
  4. 如果存在,那么将密码进行md5哈希,将其与数据库中的密码进行比对,如果不通过,那么登录失败,密码错误;
  5. 如果通过,那么将认证状态存进session或者redis,返回登录成功;
  6. 前端拿到返回成功的登录结果后,拿到Token,存入LocalStorage/cookie,后续所有请求都带有这个token,后端拦截器校验登录状态。

5、这是软件工程的核心内容,应该按照以下步骤:

  1. 需求分析&评审:梳理业务需求,输出原型图、需求文档,确定功能模块,前后端统一接口文档。
  2. 数据库设计。
  3. 架构搭建&模块拆分:搭建项目脚手架、统一返回结果、异常处理、全局拦截、工具类,按分层拆分模块,实现低耦合、高内聚。
  4. 功能迭代开发:按模块逐个开发,接口联调;
  5. 测试优化:单元测试、接口测试、压力测试、sql优化、代码规范检查、排查bug;
  6. 部署上线 & 运维监控。

6、aop是面向切面编程,aspect切面。aop底层是依靠反射和动态代理来实现的,可以定义动态代理类,需要在类上加上切面注解@Aspect,通过切入点pointcut注解,注解有一个execution切入表达式参数,这个参数就写需要被代理的方法,这样通过在调用这些方法后,就进行了一个业务增强。依靠反射机制,我们可以获取这个方法的所有信息,可以进行日志保存。通过上面两种方式,实现了在不修改业务代码的情况下,对业务代码进行加强。

7、bean的生命周期指创建到销毁的过程,常见获取bean的4种方式:

  1. Autowired和Resource注解;

  2. 通过Application Context上下文获取;

  3. 工厂方式获得,适合复杂初始化bean,mybatis整合Spring核心就是利用FactoryBean创建MapperBean;

  4. 配置类注册,在类上加@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、常见几种方式如下:

  1. 索引优化:高频查询字段建立索引,遵循最左匹配原则;
  2. sql语法优化:禁止select *,只查需要字段;大IN改exists和join;避免子查询嵌套过深;分页必须加limit;
  3. 表结构优化:字段合理设计、避免大字段查询;冷热数据分离;大表分库分表;
  4. 查询逻辑优化:优先过滤再关联;小表驱动大表;减少多表联查;
  5. 缓存优化;

9、主键索引、唯一索引、普通索引、联合索引、全文索引,底层都是B+树。

10、我这个主要回答的不是很全面,我主要从大模型获取知识源的方面进行了回答,RAG始终只是一个检索增强生成,是在LLM回答的基础上,先检索知识向量库Milvus,然后进行回答,但是这只是防止幻觉的一个方面。还有其他方面,比如说prompt提示词,显然好的提示词也可以很好的避免大模型出现乱答现象。

幻觉就是模型无依据编造答案、乱答、答非所问,核心原因 + 影响因素如下:

一、产生幻觉的核心原因

  1. 模型本身概率生成机制:大模型是基于概率预测下一个字,只会通顺、不一定正确,知识盲区会自动编造。
  2. RAG 检索不准/检索缺失:向量库匹配相似度低、检索不到有效知识,模型只能凭固有知识回答,产生错误。
  3. 上下文窗口有限:超长对话上下文丢失,信息不全导致乱答。
  4. 训练数据过时、脏数据:训练数据存在错误、老旧、偏差数据。

二、影响智能体回答质量的所有因素

  1. Prompt 质量:指令是否清晰、约束是否明确、是否限定回答范围;
  2. RAG 检索质量:向量分词、向量化模型、召回策略、相似度阈值;
  3. 上下文对话状态:对话轮次过多、信息遗忘;
  4. 模型能力:底座模型参数、微调精度;
  5. 知识库质量:知识是否准确、是否更新、是否去重纠错;
  6. 后处理机制:是否有答案校验、引用溯源、拒答机制。

AI回答:汉安数智

二、学习方法

在抖音上刷到一个博主艾坤日记,差不多6个月学习时间,完成了Java后端学习,而且还学习agent,我要向他学习,他的学习路线,学习方法。

我看了他几个视频,讲的是现在agent开发岗位除了一些头部大厂,岗位80%的内容还是和传统后端那一套,所以我要保持学习好后端,同时去学习agent。

还是要注重后端的学习,我觉得对于我来说,重要知识点最好自己实现一些,有例子,这样自己掌握更加稳固。

学习完一定要总结,后面我自己也可以使用视频的方式进行记录,说出来总是更好的,我就发布在博客园吧。

posted @ 2026-07-17 22:41  alij  阅读(5)  评论(0)    收藏  举报