三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

优秀网站psdwordpress博客蜘蛛统计

优秀网站psdwordpress博客蜘蛛统计 优秀网站psd,wordpress博客蜘蛛统计,wordpress访问加密,建站建设流程汉安数智面试10题完整标准答案(可直接背诵) 1、SQL中 IN 可以用什么优化?(全新补全) IN 的核心问题:当 IN 后面集合量大、子查询数据多时,容易走全表扫描、生成临时表、IO 高、效率差。常见优化方案有 4 种: ①… 汉安数智面试10题完整标准答案(可直接背诵) 1、SQL中 IN 可以用什么优化?(全新补全) IN 的核心问题:当 IN 后面集合量大、子查询数据多时,容易走全表扫描、生成临时表、IO 高、效率差。常见优化方案有 4 种: ① 小数据用 BETWEEN 替代 IN:连续数值场景,BETWEEN 索引命中率更高、开销更小。 ② 大数据/子查询用 EXISTS 替代 IN: IN 是先执行子查询、再匹配外层;EXISTS 是先遍历外层表、逐行判断是否存在匹配数据。 外层表小、子查询结果大时,EXISTS 性能远优于 IN。 实战例子(一眼看懂区别) 场景:查询「有过订单的用户」 用户表 user(1000 条,小表) 订单表 order(100 万条,大表) 【IN 写法(低效)】 SELECT * FROM user WHERE id IN (SELECT user_id FROM order); 原理:先把 100 万条订单全部查出来生成临时结果集,再和用户表匹配,数据量大极耗 IO。 【EXISTS 写法(高效)】 SELECT * FROM user u WHERE EXISTS (SELECT 1 FROM order o WHERE o.user_id = u.id); 原理:遍历外层小表用户,每遍历一个用户,就去大订单表匹配到第一条就立刻终止,不会查全量数据,极大提升效率。 总结口诀(面试必背) 大结果集用 EXISTS,小连续数值用 BETWEEN,复杂关联用 JOIN,坚决不用 NOT IN。 ③ 用 JOIN 联表查询替代 IN 子查询(最优常用): 把 IN 的匹配逻辑改成 INNER JOIN / LEFT JOIN,数据库可以高效走索引关联,避免临时表和全扫,是生产最常用的 IN 优化手段。 ④ 超大 IN 集合拆分、分批查询: IN 元素过万时性能暴跌,可以拆分批次查询、或者导入临时表关联查询,避免单次 IN 过大导致超时。 补充禁忌:禁止 NOT IN(有 NULL 会查不到数据、极易踩坑),统一用 NOT EXISTS 替代。 2、线程锁有哪些?(全新补全) Java 面试常答、工作常用锁分两大类:内置锁(悲观锁)、JUC 显式锁,外加细分锁机制: 1)synchronized 内置锁 底层依赖 JVM 实现,可锁方法、代码块;自动加锁释放、不用手动控制;属于可重入、悲观、独占锁。 2)ReentrantLock 可重入显式锁 JUC 手动锁,功能比 synchronized 更强:可手动加解锁、可超时锁、可中断锁、支持公平/非公平锁。 3)读写锁 ReentrantReadWriteLock 读多写少场景专用:读锁共享、写锁独占,大幅提升并发读性能(比如缓存、配置查询)。 4)自旋锁(通俗详解+例子) 核心大白话:不睡觉、一直重试 普通锁(synchronized):拿不到锁就阻塞休眠,线程挂起、让出CPU,等别人释放锁再唤醒。 缺点:休眠、唤醒需要系统调度,开销大。 自旋锁:拿不到锁不阻塞、不休眠,就在原地循环空转、不断尝试抢锁,直到抢到为止。 生活化例子: 排队上厕所: 1. 普通悲观锁:没位置我直接蹲旁边睡觉,有人出来再喊我(要唤醒,慢)。 2. 自旋锁:没位置我不睡觉,一直站门口反复看、反复问有没有空位,一旦有人出来我立刻进去(极快)。 适用场景(面试必背): 锁持有时间非常短、竞争不激烈。 因为等待时间很短,空转的CPU开销 线程休眠唤醒的开销。 缺点: 如果别人锁持有很久,自旋会一直空跑、白白占用CPU,导致CPU飙高。 面试一句话总结: 自旋锁是循环抢锁、不阻塞、不空歇,短时等待性能极高,长时等待浪费CPU。 5)悲观锁 乐观锁(数据库层面,带通俗解释+实战例子) 一、悲观锁(顾名思义:极度悲观) 核心思想:我默认别人一定会抢我的数据、一定会改。所以我一查数据就直接上锁,别人不能读也不能改,等我事务结束才释放。 实现方式:SELECT ... FOR UPDATE 实战例子(库存扣减): 我要扣商品库存,我先加锁锁住这条库存数据,别人排队等着改,杜绝超卖。 特点:独占、安全、并发低、性能差,适合并发不高、数据冲突多的场景。 二、乐观锁(顾名思义:极度乐观) 核心思想:我默认别人不会改我的数据,所以我全程不上锁,读写随便搞,只在最后更新的时候校验一下有没有被别人改过。 实现方式:版本号 version / 时间戳 实战例子(版本号机制): 1、查询数据时,拿到 version=1; 2、业务处理逻辑; 3、更新时校验:update set stock=stock-1,version=version+1 where id=1 and version=1; 4、如果此时别人已经改了数据,version 变成2,我的更新失败,重试即可。 特点:无锁、并发高、性能好,适合高并发、冲突少的场景(电商、订单系统主流)。 面试绝杀总结: 悲观锁:先锁再操作,防冲突,牺牲性能换安全; 乐观锁:先操作后校验,无阻塞,高性能高并发首选。 6)分段锁(通俗详解+例子) 核心原理:不锁整张表、不锁整个容器,只锁当前操作的一小段。 通俗类比(秒懂): 如果整个厕所只有一把锁(全局锁):一个人进去,所有人都得等,并发极差,效率极低。 分段锁就是:把厕所分成16个小隔间,每个隔间一把锁。 你只用锁住你正在用的那一间,别人可以正常用其他隔间,互不影响,并发直接拉满。 经典场景:JDK1.7 ConcurrentHashMap 它把整个大集合分成 16个Segment分段: 1、修改数据时,只锁当前这一段; 2、其他15段数据照常读写,不会被阻塞; 3、相比 Hashtable 锁住整个集合,分段锁极大减小了锁粒度,大幅提升并发性能。 面试一句话总结: 分段锁就是化整为零、分段加锁,减小锁竞争范围,是高并发场景优化锁性能的核心手段。 3、点餐覆盖是什么意思?(全新补全,业务标准答案) 这是外卖/点餐系统经典业务名词,点餐覆盖 = 新下单/改单覆盖旧的未结算订单内容,核心场景: 1、用户下单后、商家未接单/未出餐时,用户重新下单、或者修改菜品、规格、数量,系统用最新订单数据覆盖旧订单,旧订单作废,以新单为准。 2、覆盖规则:只覆盖未支付、未接单、未完成的有效订单;已接单、已出餐、已结算订单不允许覆盖,只能走退单、改单流程。 业务目的:避免用户重复下单、冗余脏订单,保证同一桌/同一用户同一时段只有一条有效待处理订单。 4、前端到后端数据库完整业务场景(登录模块)【你的版本已大幅完善、修正漏洞】 我以用户登录完整链路,从前端、网络、后端 MVC、权限、缓存、数据库,给你一套标准面试完整版: 1. 前端层 用户输入账号密码,前端做基础非空、格式校验,通过 Ajax/axios 异步 POST 请求,把表单数据传给后端接口。 2. 网络与拦截层 请求经过 Nginx 转发、全局拦截器,到达后端 SpringMVC 的 DispatcherServlet 前端控制器,统一拦截所有请求。 3. 路由匹配 DispatcherServlet 根据 URL 路径匹配 @RequestMapping,定位到对应的 LoginController 控制器方法。 4. Controller 层(参数校验、调用业务) 接收账号密码,做参数校验,调用 UserService 登录业务方法。 5. Service 层(核心业务逻辑) ① 查询 Redis 缓存,判断用户是否已登录、Token 是否有效,有效直接返回登录成功; ② 缓存未命中,调用 Mapper 查询数据库用户信息; ③ 判断用户名是否存在,不存在返回账号错误; ④ 对前端明文密码做 MD5/SM3 加密,和数据库密文密码比对; ⑤ 密码一致则登录成功,不一致返回密码错误; ⑥ 登录成功后,JWT 生成唯一 Token,存入 Redis(设置过期时间),返回给前端。 6. Dao/Mapper 层 通过 Mybatis 执行 SQL,查询用户表账号、加密密码、状态等数据,返回给业务层。 7. 数据库层 存储用户基础信息,密码密文存储,字段加索引保证查询速度。 8. 前端响应处理 前端拿到 Token,存入 localStorage / cookie,后续所有接口请求携带 Token,后端拦截器校验登录态。 亮点补充(面试加分):整条链路实现了前端校验、后端幂等、缓存提速、密码加密、无状态登录、权限拦截的完整闭环。 5、开发一个项目的流程、模块如何衔接?(全新补全,面试标准流程) 完整项目开发流程,从 0 到 上线,分为 6 步,同时讲清模块衔接: 1)需求分析 评审 梳理业务需求、输出原型图、需求文档,确定功能模块(登录、订单、用户、支付等),前后端统一接口文档。 2)数据库设计 设计表结构、字段、索引、主键、外键、关联关系,确定分表、字典、状态字段,提前规避慢查询。 3)架构搭建 模块拆分 搭建项目脚手架、统一返回结果、异常处理、全局拦截、工具类。 按分层拆分模块:Controller 接口层、Service 业务层、Dao 数据层、Entity 实体层、Utils 工具层。 模块衔接规则: Controller 只接收请求、不写业务; Service 处理核心业务、事务控制、模块调用; Dao 只负责数据库 CRUD; 各层单向调用,解耦清晰。 4)功能迭代开发 按模块逐个开发、接口联调,前后端对接测试。 5)测试优化 单元测试、接口测试、压力测试、SQL 优化、代码规范检查、Bug 修复。 6)部署上线 运维监控 打包、部署服务器、配置 Nginx、日志监控、异常告警、线上迭代维护。 6、AOP 具体原理(你的版本深度完善、标准化) AOP 全称面向切面编程,核心思想:不修改原有业务代码的前提下,对方法进行统一增强。 1、底层原理 基于 Java 动态代理 + 反射机制 实现: 目标类有接口用 JDK 动态代理;无接口用 CGLIB 字节码代理。 2、核心组件 ① 切面 @Aspect:定义切面类,存放所有增强逻辑; ② 切入点 @Pointcut:通过 execution 表达式匹配需要拦截的所有目标方法; ③ 通知:前置、后置、返回后、异常、环绕通知,在方法执行前后做增强。 3、执行流程 程序调用目标方法 → Spring 识别切入点匹配 → 生成代理对象 → 通过反射拦截方法执行 → 执行自定义切面逻辑(日志、权限、事务、限流)→ 执行原有业务方法。 4、实际用途(面试加分) 统一日志记录、统一权限校验、事务控制、接口限流、性能监控、参数脱敏。 7、Bean 的生命周期 + 获取 Bean 实例的方式(全新补全,高频面试题) 一、Spring Bean 完整生命周期(标准 6 步) 1. 实例化:Spring 扫描注解,通过反射创建 Bean 空对象; 2. 属性填充:自动装配 @Autowired、依赖注入; 3. 初始化前置处理:执行 Bean 后置处理器前置方法; 4. 初始化:执行 InitializingBean、自定义 init-method; 5. 初始化后置处理:执行 Bean 后置处理器后置方法; 6.销毁:容器关闭时执行 DisposableBean、destroy-method。 二、获取 Bean 实例的 4 种方式****(附实战代码例子) 1. 注解注入(@Autowired、@Resource,项目最常用) Spring 自动注入容器中的Bean,无需手动创建,日常开发主流用法。 @Service public class UserService {// 自动从Spring容器中获取UserMapper Bean实例@Autowiredprivate UserMapper userMapper; } 2. 手动获取(ApplicationContext上下文getBean()) 适用于非Spring管理的普通类,手动从容器中获取Bean实例。 // 获取Spring上下文 ApplicationContext context = SpringContextUtil.getApplicationContext(); // 根据Bean类型获取实例 UserService userService = context.getBean(UserService.class); // 根据Bean名称获取实例 UserService userService2 = (UserService) context.getBean("userService"); 3. 工厂方式(FactoryBean自定义创建Bean) 用于自定义复杂Bean的创建逻辑,Mybatis整合Spring核心就是利用FactoryBean创建MapperBean。 public class CustomBeanFactory implements FactoryBeanUser {@Overridepublic User getObject() throws Exception {// 自定义Bean创建、初始化逻辑User user = new User();user.setUsername("test");return user;}@Overridepublic Class? getObjectType() {return User.class;} }// 注册工厂Bean @Bean public CustomBeanFactory customBeanFactory(){return new CustomBeanFactory(); } 4. 配置类注册(@Bean注解手动注册实例) 用于第三方类、无法添加注解的类,手动将对象注入Spring容器。 @Configuration public class BeanConfig {// 手动创建Bean并交给Spring容器管理@Beanpublic RedisTemplateString, Object redisTemplate(RedisConnectionFactory factory){RedisTemplateString, Object redisTemplate = new RedisTemplate();redisTemplate.setConnectionFactory(factory);return redisTemplate;} } 8、SQL 常见优化方式(你的版本大幅扩充、系统化) 我整理面试最全、最稳的一套答案: 1、索引优化(核心) 高频查询字段建索引;遵循最左匹配原则;避免索引失效(like %前缀、函数运算、隐式类型转换、or 滥用)。 2、SQL 语句写法优化 禁止 select *,只查需要字段; 大 IN 改 JOIN/EXISTS; 避免子查询嵌套过深; 分页必须加 limit,避免全量返回。 3、表结构优化 字段合理设计、避免大字段查询;冷热数据分离;大表分库分表、分区表。 4、查询逻辑优化 优先过滤再关联;小表驱动大表;减少多表联查;合理使用临时表。 5、缓存优化 高频查询数据放 Redis,减少数据库查询压力。 6、执行计划优化 通过 explain 分析 SQL,定位全表扫描、索引失效、临时表、文件排序问题。 9、数据库索引类型(你的版本完善、全覆盖) 面试必答 5 类索引: 1. 主键索引(PRIMARY) 唯一、非空、一张表只能一个,查询速度最快。 2. 唯一索引(UNIQUE) 字段值唯一、可空,用于手机号、账号等唯一字段。 3. 普通索引(INDEX) 最基础索引,无唯一限制,用于普通查询提速。 4. 联合/复合索引 多个字段组合索引,遵循最左前缀原则,避免重复建多个单索引。 5. 全文索引 用于文章、内容长文本模糊检索。 补充面试加分:底层结构都是 B+ 树,索引本质是空间换时间。 10、大模型/智能体幻觉原因、影响回答质量的因素(你的版本全面升级) 幻觉就是模型无依据编造答案、乱答、答非所问,核心原因 + 影响因素如下: 一、产生幻觉的核心原因 1. 模型本身概率生成机制:大模型是基于概率预测下一个字,只会通顺、不一定正确,知识盲区会自动编造。 2. RAG 检索不准/检索缺失:向量库匹配相似度低、检索不到有效知识,模型只能凭固有知识回答,产生错误。 3. 上下文窗口有限:超长对话上下文丢失,信息不全导致乱答。 4. 训练数据过时、脏数据:训练数据存在错误、老旧、偏差数据。 二、影响智能体回答质量的所有因素 1. Prompt 质量:指令是否清晰、约束是否明确、是否限定回答范围; 2. RAG 检索质量:向量分词、向量化模型、召回策略、相似度阈值; 3. 上下文对话状态:对话轮次过多、信息遗忘; 4. 模型能力:底座模型参数、微调精度; 5. 知识库质量:知识是否准确、是否更新、是否去重纠错; 6. 后处理机制:是否有答案校验、引用溯源、拒答机制。(注:部分内容可能由 AI 生成)
← 返回列表