SaaS-Admin-项目八股文
这块用 ELK,应用日志收集到 Elasticsearch,再通过 Kibana 检索和分析,主要看异常日志、慢请求这些。元素进来之后先算 hash,再定位到数组下标;对我来说,这个方案比“在代码里同时写 MySQL 和 ES”更稳定,因为后者侵入性强,也容易遗漏。它的非叶子节点只存索引,不存完整数据,所以一页能放更多索引,树高度更低,磁盘 IO 更少。对我来说,监控的意义不只是“看图”,更重要的
19. HashMap 底层原理怎么说?
HashMap 在 JDK1.8 之后底层是 数组 + 链表 + 红黑树。
元素进来之后先算 hash,再定位到数组下标;如果那个位置为空就直接放进去,不为空就看是链表还是红黑树。
如果链表太长,并且数组容量也足够大,就会转成红黑树,提高查询效率。
它线程不安全,所以并发场景一般用 ConcurrentHashMap。
20. ConcurrentHashMap 原理怎么说?
JDK1.7 的 ConcurrentHashMap 用的是 Segment 分段锁,
JDK1.8 之后把 Segment 去掉了,改成 CAS + synchronized。
简单理解就是:能无锁就尽量 CAS,冲突了再锁更小粒度的节点,所以并发性能会更好。
它比 Hashtable 性能高很多,也是并发场景下最常用的 Map。
21. ThreadLocal 为什么会内存泄漏?
因为 ThreadLocalMap 里的 key 是弱引用,key 可能被回收掉,但是 value 还在。
如果线程又是线程池这种长生命周期线程,那 value 就可能一直挂着,造成内存泄漏。
所以 ThreadLocal 用完之后一定要remove(),最好放在 finally 里清理。
22. Spring 事务为什么会失效?
最常见的几个场景:
第一,方法不是 public;
第二,同类内部调用,没有走代理;
第三,异常被自己 catch 掉了,没往外抛;
第四,抛的是受检异常,但没配置rollbackFor。
本质上就是:Spring 事务是基于 AOP 代理的,只要没走到代理逻辑,事务就可能失效。
23. MySQL 索引为什么用 B+ 树?
因为 B+ 树特别适合数据库这种磁盘存储场景。
它的非叶子节点只存索引,不存完整数据,所以一页能放更多索引,树高度更低,磁盘 IO 更少。
同时叶子节点之间还是有序链表,天然支持范围查询和排序。
这也是为什么数据库默认更倾向用 B+ 树而不是普通二叉树或者红黑树。
24. Redis 缓存穿透、击穿、雪崩怎么说?
穿透是查一个根本不存在的数据,请求每次都打到数据库;
击穿是某个热点 key 过期了,大量请求同时打到数据库;
雪崩是很多 key 同时过期,数据库瞬间被压垮。
应对方式一般分别是:
穿透用布隆过滤器或者缓存空值;
击穿用互斥锁或者热点永不过期;
雪崩用随机过期时间、集群、限流降级。
25.系统监控和告警是怎么做的?
我们监控分成三块:日志、指标、告警。
日志这块用 ELK,应用日志收集到 Elasticsearch,再通过 Kibana 检索和分析,主要看异常日志、慢请求这些。
指标这块用 Prometheus + Grafana,监控 JVM 内存、CPU、接口 QPS、响应时间、数据库连接池、Redis 命中率等核心指标。
告警这块会在指标超过阈值时通过邮件、短信或者钉钉通知出来,比如 CPU 过高、内存过高、连接池快满、错误日志突增。
对我来说,监控的意义不只是“看图”,更重要的是能不能尽早发现问题、快速定位问题。
所以我比较看重监控、日志、告警三者打通。
26.Elasticsearch 如何和 MySQL 保持同步?
我们采用的是 Canal + 消息队列 + ES 的异步同步方案。
MySQL 开启 binlog 之后,Canal 去订阅数据库变更,然后把增删改事件发送到消息队列,下游再消费这些消息写入 Elasticsearch。
这样做有几个好处:
第一,和业务代码解耦,不需要每次业务更新都手动同步 ES;
第二,实时性比较好,通常延迟可以控制在 1 秒左右;
第三,扩展性更强,后续如果还想同步给别的系统,也可以复用这条链路。
对我来说,这个方案比“在代码里同时写 MySQL 和 ES”更稳定,因为后者侵入性强,也容易遗漏。
所以同步链路上,我们更看重解耦和可扩展性。
加分点
你可以顺带补一句:ES 最终一致即可,不要求和 MySQL 强一致。
27.你们基于 Velocity 的代码生成器是怎么做的?
这个代码生成器本质上就是“读取表结构 + 组装元数据 + 套模板生成代码”。
先从information_schema里读取数据库表名、字段名、字段类型、注释这些元信息;
然后把这些信息转换成 Java 里的类名、属性名、类型映射,比如下划线转驼峰、MySQL 类型映射成 Java 类型;
最后把这些数据塞进 Velocity 模板,批量生成 Entity、Mapper、Service、Controller 这些代码。
这样做最大的价值是统一代码风格,减少重复劳动。
加分点
生成器解决的不是“不会写代码”,而是“减少低价值重复劳动”。
更多推荐
所有评论(0)