avatar
文章
73
标签
209
分类
30
首页
简历
技术文章
时间图
分类
标签
关于
高晓庄 札记
首页
简历
技术文章
时间图
分类
标签
关于

高晓庄 札记

一个定时任务从 14 分钟优化到 2 分钟
发表于2026-03-05|JavaPerformance
一个定时任务从 14 分钟优化到 2 分钟 “我会 Spring Boot”很普通,”我解决过一个线上任务内存 15G+、耗时十几分钟的问题”才有价值。这篇文章复盘一次真实的性能优化。 问题现象一个每天凌晨跑的数据同步任务,负责把外部系统的数据拉取、清洗、写入本地库。最初数据量小没感觉,随着数据积累到几百万条,问题集中爆发: 执行时间从 2 分钟一路涨到 14 分钟 内存峰值 15G+,频繁触发 Full GC 偶尔直接把服务 OOM 打挂 排查过程第一步:定位耗时点在任务里埋了几个计时点,发现 90% 的时间都花在”写入数据库”这一步,而不是拉取或清洗。 第二步:找到内存杀手用 JVM 的堆 dump 分析,发现内存里堆了 几十万个待写入的对象。原因是一开始的写法是”查一条、改一条、写一条”,后来为了”提速”改成了”全部加载进内存、最后一次性批量写”——结果把内存打爆了。 第三步:分析根因真正的根因是没有分批(batching)+ 逐条 UPDATE 没有走批量。数据量大之后,逐条执行的开销是指数级增长的。 优化方案1. 流式处理 + 分批不再把所有数据 load 进内存...
整洁代码与代码审查:写出别人愿意读的代码
发表于2026-02-26|基础
有个说法我很认同: 代码是写给人读的,只是顺便让机器执行。 代码的正确性当然重要,但如果一段代码除了作者谁都读不懂,那它就是个”定时炸弹”——三个月后连作者自己都读不懂了。 这一篇是”基础系列”的收尾,聊一个软性但极重要的话题:怎么写出整洁、可维护的代码。 命名:代码可读性的第一道关命名的目标是:让人不读注释,光看名字就知道是什么意思。 几个原则: 用能表达意图的名字:d 不如 elapsedDays,process() 不如 calculateOrderTotal() 避免缩写:usrNm 不如 userName 布尔值用疑问句:isValid、hasPermission、isEmpty 方法名用动词:getUser、createOrder、validateInput 一个反例: 1int d; // 天数 一个正例: 1int elapsedDays; 好名字是免费的文档,不要吝啬。 函数:小而专一一个函数应该只做一件事,并且要短。 判断标准: 函数是否小到”一眼能看完”?理想是 20 行以内 函数是否只做了一件事?如果描述它需要”和”字,就该拆 函数的嵌套层级...
并发编程基础:线程、锁与内存可见性
发表于2026-02-22|基础
如果说单线程编程是”确定性的世界”,那并发编程就是”不确定性的世界”。 多线程 bug 之所以难查,是因为它不是每次都复现——可能跑了 100 次都正常,第 101 次突然出错。 要驾驭并发,得先理解它为什么难。 并发问题的三大根源1. 原子性:一个操作被”打断”比如 count++,看起来是一步,实际上是三步: 读取 count 的值 加 1 写回 count 两个线程同时执行 count++,可能都读到 0,都加 1,都写回 1,结果本应是 2,却变成了 1。 这就是原子性问题:多个步骤的操作,在执行过程中被别的线程插入了。 解决:用锁(synchronized、Lock)或原子类(AtomicInteger)保证操作不可分割。 2. 可见性:改了但别人看不到每个线程都有自己的工作内存(缓存),变量修改可能先改在缓存里,没有及时同步到主内存。 结果就是:线程 A 改了变量,线程 B 却看不到,还在读旧值。 这就是可见性问题。解决:用 volatile 关键字,保证变量修改立刻对其他线程可见。 volatile 的作用是:保证可见性 + 禁止指令重排序。注意它不保证原子性,...
企业级微服务基础平台设计
发表于2026-02-19|ArchitectureEnterprise Architecture
企业级微服务基础平台设计 当公司同时有几十个系统在跑,每个系统都自己实现一遍登录、权限、菜单、数据同步,这就是巨大的浪费。基础平台的价值,是把这些重复建设收敛成一套统一能力。 为什么要做统一技术底座接手基础研发后我面对的现实是:公司内部巡检、安全、应急、设备、GIS、气量等业务系统,加上 ERP、客服、营收等外部系统,各自为战。同样的认证逻辑被写了十几遍,安全策略不统一,新项目交付周期长。 统一底座要解决三个核心问题:重复建设、安全不统一、交付慢。 通用能力的抽象经过梳理,我们把所有系统的共性能力抽象成下面几块: 能力 解决什么问题 统一认证 一个账号登录所有系统(SSO) RBAC 权限 统一的用户-角色-资源授权模型 多租户 不同客户/组织数据隔离 菜单集成 各系统菜单统一编排到门户 主数据同步 用户、组织等基础数据一处维护、多处使用 文件服务 统一的文件上传、存储、访问控制 消息通信 系统间异步消息与轨迹数据通道 定时任务 统一的任务调度与监控 这些能力每一个单独看都不难,难的是把它们收敛成一套稳定、可复用、可运维的体...
递归与回溯:从汉诺塔到全排列
发表于2026-02-16|基础
递归是很多人学习路上的一道坎。 它的反直觉之处在于:你没法在脑子里完整地展开整个递归过程,越想越晕。 但其实递归有套路可循,掌握了套路,就能”以不变应万变”。 递归的三要素任何递归问题,都必须明确三件事: 递归的定义:这个函数要做什么?(返回什么、有什么效果) 递归的终止条件:什么时候不再递归,直接返回? 递归的递推关系:怎么把大问题拆成子问题? 以经典的斐波那契为例: 1234int fib(int n) { if (n <= 1) return n; // 终止条件 return fib(n-1) + fib(n-2); // 递推关系} 想递归的正确姿势新手最容易犯的错,是在脑子里展开递归树——“fib(5) 调用 fib(4),fib(4) 又调用 fib(3)……”,然后彻底乱掉。 正确姿势是只关注当前这一层: 假设子问题已经解决了(相信递归) 只思考”怎么用子问题的结果,得到当前问题的结果” 然后补上终止条件 就像数学归纳法:假设 n-1 成立,证明 n 成立,再验证 n=1 成立。你不...
二分查找:边界条件为什么总是写错
发表于2026-02-13|基础
二分查找有个著名的梗:“一看就会,一写就错”。 甚至有人统计过,能一次写对二分查找的工程师不到 20%。 问题几乎全出在一个地方:边界条件。今天把它彻底讲透。 二分查找的前提二分查找只能用于有序数组(或单调序列)。 它的核心思想:每次取中间值,和目标比大小,直接排除一半。 1234567891011121314int binarySearch(int[] nums, int target) { int left = 0, right = nums.length - 1; while (left <= right) { int mid = left + (right - left) / 2; if (nums[mid] == target) { return mid; } else if (nums[mid] < target) { left = mid + 1; } else { ...
排序算法:快排、归并、堆排,理解比背诵重要
发表于2026-02-10|基础
排序算法大概是算法入门绕不开的第一课,也是面试里被问得最多的话题之一。 但很多人学排序的方式是”背代码”,结果背了忘、忘了背。 其实只要抓住每个算法的核心思想,代码自然就能写出来。 先记住这个底线基于比较的排序算法,时间复杂度有理论下界:O(n log n)。 也就是说,任何”靠比较大小来排序”的算法,最优也就是 O(n log n),不可能更快(除非用计数排序、桶排序这种不基于比较的特殊算法)。 所以快排、归并、堆排,都是已经摸到比较排序天花板的算法。 快速排序:分治 + 分区快排的核心是分区(partition):选一个”基准值(pivot)”,把数组分成两部分——左边都比 pivot 小,右边都比 pivot 大。然后对左右两部分递归做同样的事。 123456void quickSort(int[] arr, int lo, int hi) { if (lo >= hi) return; int p = partition(arr, lo, hi); // 分区,返回 pivot 位置 quickSort(arr, lo, p - 1);...
图与图的遍历:BFS、DFS 与拓扑排序
发表于2026-02-07|基础
前面讲的都是”线性”(数组、链表)和”层次”(树)结构。但现实中有大量关系是”网状”的: 社交网络里,谁关注谁 城市之间,怎么导航 项目里,任务之间的依赖 这些用树表达不了,因为树不允许”环”,而现实关系到处是环。这时候就需要图。 图的基本概念图由**顶点(Vertex)和边(Edge)**组成。 按边的方向,分为: 无向图:边没有方向(如”互为好友”) 有向图:边有方向(如”A 关注了 B”,单向) 按边是否带权重,分为: 无权图:边都一样 带权图:边有权重(如”两个城市之间的距离”) 图的两种存储方式1. 邻接矩阵用一个二维数组 matrix[i][j] 表示”从 i 到 j 是否有边”。 优点:判断”i 和 j 是否有边”是 O(1),简单直观 缺点:空间 O(n²),稀疏图(边很少)会浪费大量空间 2. 邻接表每个顶点维护一个”它指向的邻居”列表。 优点:空间 O(V + E),稀疏图很省 缺点:判断”i 和 j 是否有边”要遍历 i 的邻居列表,O(度数) 工程上邻接表更常用,因为现实中的图大多是稀疏的。 广度优先遍历(BFS)BFS 按”层”逐层向...
1…678…10
avatar
高晓庄
Java / Go / Python
AI / RAG / Agent
Cloud Native / Kubernetes
文章
73
标签
209
分类
30
Follow Me
最新文章
腾讯 Hy4 首发速评:770B 跑分该怎么读2026-11-04
善待自己是一剂不保证有效的药方 — 听程乐松讲2026-09-10
听《十字路口》刘震云那一期,我突然不焦虑了——一个普通人的几个共鸣2026-09-08
关于"内卷"的经济学解释——读《人月神话》和薛兆丰之后2026-09-05
不确定性是人生唯一确定的事——我不再假装掌控一切2026-09-01
分类
  • AI31
    • Agent2
    • Architecture1
    • CV1
    • Dify1
    • LLM2
    • RAG1
  • Architecture3
标签
n8n Claude Code DFS Copilot 王阳明 HashMap 注意力机制 单元测试 多线程 QLoRA MetaGPT 工程化 开发范式 TDD 人生 开篇 Prompt 架构 Function Calling 工程 智能问数 Gemini 中年 MySQL Docker BabyAGI AI工作流 向量数据库 代码审查 Tool Use 函数式编程 Flannel 检索增强 网络排障 记忆 自动化 递归 云原生 单例模式 Self-RAG
归档
  • 2026-11 1
  • 2026-09 4
  • 2026-08 16
  • 2026-07 10
  • 2026-06 7
  • 2026-05 4
  • 2026-04 5
  • 2026-03 2
网站信息
文章数目 :
73
本站总字数 :
88.5k
本站访客数 :
本站总浏览量 :
最后更新时间 :
© 2025 - 2026 By 高晓庄