沉淀知识,持续成长
记录 Java 后端、前端开发与 Linux 运维的每一次思考与实战踩坑。
📖 最新技术笔记
Spring Boot 自动装配原理深度解析
从 @SpringBootApplication 注解入手,分析 @EnableAutoConfiguration 如何通过 SPI 机制加载 META-INF/spring.factories 中的配置类...
JVM 内存模型与垃圾回收机制总结
整理堆、栈、方法区的内存划分,以及新生代 Eden/Survivor 比例。重点记录 CMS 和 G1 收集器的适用场景与调优参数...
MySQL 索引优化与 Explain 执行计划分析
记录最左前缀原则、索引下推。通过 Explain 命令分析 type、key、rows 等字段,定位并解决慢 SQL 问题...
Redis 缓存穿透、击穿与雪崩的解决方案
结合实际项目,总结布隆过滤器、互斥锁、逻辑过期等应对策略,以及如何通过多级缓存降低 Redis 压力...
Synchronized 锁升级与 AQS 框架解析
从 JVM 字节码指令 monitorenter/exit 到 AQS 框架,对比两者的锁升级过程、公平锁与非公平锁的实现差异...
Spring 事务失效的 8 种常见场景
方法非 public、自调用、异常被吞、事务传播行为配置错误等导致 @Transactional 失效的场景与排查思路...
Spring Cloud Alibaba 微服务组件整合实战
整合 Nacos 作为注册中心和配置中心,OpenFeign 实现服务调用,Sentinel 实现限流降级,Gateway 统一网关...
Kafka 消息丢失与重复消费问题排查
从生产者 acks 机制、Broker 持久化,到消费者 offset 提交策略,全方位分析 Kafka 消息可靠性保障方案...
Vue3 响应式原理:Proxy 与 Reflect 深度解析
对比 Vue2 的 Object.defineProperty,分析 Vue3 如何利用 Proxy 实现深层响应式,以及依赖收集与触发更新的流程...
React Hooks 闭包陷阱与性能优化实践
记录 useState 异步更新、useEffect 依赖数组常见坑点,以及 useMemo、useCallback 在组件性能优化中的正确用法...
TypeScript 泛型与高级类型实战总结
整理 Partial、Omit、Pick 等内置工具类型的实现原理,以及如何在项目中利用泛型约束提升代码类型安全性...
前端性能优化:从首屏加载到 Lighthouse 评分
通过路由懒加载、图片压缩、CDN 加速、Gzip 压缩等手段,将首屏加载时间从 3s 优化到 1s 以内的实战记录...
Vite 与 Webpack 打包构建原理对比
分析 Vite 为什么在开发环境下冷启动如此之快(ESBuild + ESM),以及 Webpack 的依赖图谱构建流程差异...
使用 Docker 部署 Spring Boot 项目实战
编写 Dockerfile,利用多阶段构建减小镜像体积。配置 docker-compose 一键启动 MySQL、Redis 和应用服务...
K8s 核心概念:Pod、Deployment 与 Service
从零开始理解 K8s 的编排模型,记录 Pod 生命周期、Deployment 滚动更新策略以及 Service 服务发现的配置...
Nginx 编译安装后,Certbot 无法找到配置的解决方案
记录在非标准路径下编译安装 Nginx 时,如何通过软链接与参数指定,让 Certbot 正常签发 SSL 证书...
Linux 排查 CPU 飙高的实用命令与思路
通过 top、pidstat、jstack 等工具,定位 Java 进程 CPU 100% 的具体线程与代码行,记录一次真实线上排查过程...
单页应用(SPA)路由回退原理与 Nginx 配置
为什么访问不存在的路径会返回首页?try_files 指令是如何工作的?本文记录一次实际踩坑过程...
Shell 脚本自动化:定时备份 MySQL 与日志清理
编写 Shell 脚本结合 crontab,实现 MySQL 数据库每日自动备份、压缩,并清理 7 天前的旧日志与备份文件...
Prometheus + Grafana 搭建服务器监控系统
使用 Node Exporter 采集 Linux 主机指标,Prometheus 存储时序数据,Grafana 配置可视化大屏并设置告警规则...
个人网站从零到上线:域名备案与 HTTPS 配置全记录
整理从购买服务器、域名解析、提交 ICP 备案,到最终使用 Let's Encrypt 开启 HTTPS 的完整流程...
💡 常见技术问答
什么是跨域?如何解决跨域问题?
- CORS:后端设置
Access-Control-Allow-Origin等响应头。 - Nginx 反向代理:通过同源服务器转发请求。
- JSONP:老式方案,利用
<script>标签不受同源策略限制。 - 开发环境代理:如 Vite/Webpack 的 proxy 配置。
Vue2 和 Vue3 的响应式原理有什么区别?
- Vue2:基于
Object.defineProperty实现。缺点是无法监听对象属性的新增和删除,也无法监听数组下标的变化(需要重写数组方法)。 - Vue3:基于
Proxy和Reflect实现。可以代理整个对象,支持动态新增属性、删除属性,并且能完美监听数组变化,性能更好,且支持深层响应式。
Spring 是如何解决循环依赖的?
- 一级缓存 (singletonObjects):存放完全初始化好的 Bean。
- 二级缓存 (earlySingletonObjects):存放提前暴露的、尚未填充属性的原始 Bean。
- 三级缓存 (singletonFactories):存放 Bean 的 ObjectFactory,用于生成原始 Bean 或代理对象。
什么是数据库的乐观锁和悲观锁?
- 悲观锁:认为并发冲突一定会发生,操作数据时直接加锁(如
SELECT ... FOR UPDATE)。适合写多读少的场景。 - 乐观锁:认为并发冲突不常发生,提交更新时才检查版本号或时间戳。适合读多写少的场景,通常通过
version字段实现。
ThreadLocal 为什么会发生内存泄漏?
解决办法:使用完 ThreadLocal 后,务必在
finally 块中调用 remove() 方法清理。
如何保证缓存与数据库的双写一致性?
- 先更新数据库,再删除缓存(Cache Aside Pattern):最常用,但在极端并发下仍有脏数据风险。
- 延迟双删:更新数据库前后各删除一次缓存,并在中间加短暂延迟,降低脏数据概率。
- 订阅 MySQL Binlog:如 Canal 监听数据库变更,异步刷新缓存,实现最终一致性。
- 分布式锁:在更新时加锁,保证读写串行,但会牺牲性能。
如何排查 Linux 服务器 CPU 使用率过高的问题?
- 使用
top找到 CPU 最高的进程 PID。 - 如果是 Java 进程,使用
top -Hp [PID]找到占用 CPU 最高的线程 TID。 - 将 TID 转为十六进制:
printf "%x\n" [TID]。 - 使用
jstack [PID] | grep [十六进制TID] -A 20定位到具体代码行。 - 如果是非 Java 进程,可使用
perf top或strace分析。
Docker 和虚拟机有什么区别?
- 虚拟机:在宿主机上模拟硬件,运行完整的操作系统,资源占用大,启动慢(分钟级),隔离性强。
- Docker 容器:共享宿主机内核,通过 Namespace 实现隔离,Cgroups 限制资源。启动快(秒级),占用资源少,但隔离性弱于虚拟机。
Certbot 报错 "Could not find a usable 'nginx' binary" 怎么办?
/usr/local/nginx),不在系统默认的 PATH 中。可以通过创建一个软链接(ln -s /usr/local/nginx/sbin/nginx /usr/local/bin/nginx),或者在运行 Certbot 时显式指定路径(如添加 --nginx-ctl 和 --nginx-server-root 参数)来解决。
Nginx 正向代理和反向代理的区别?
- 正向代理:代理客户端,客户端知道自己在访问代理服务器,服务器不知道真正的客户端是谁(如翻墙工具)。
- 反向代理:代理服务器端,客户端不知道自己在访问代理服务器,以为直接访问了目标服务器(如 Nginx 负载均衡)。