从今天起开一个固定栏目:每天读一本书,把里面的东西压缩到 20 分钟内读完,再写点自己的看法。方向是金融、AI、历史这三块——前两块是饭碗,最后一块是让人不至于把今年发生的事都看成世界末日。 这个栏目不打算做成读书笔记的搬运。我做了八年 Java 和 AI,又自己跑过出海盘子、也清零过两次,读这些书
Java 也要有自己的 AI 抽象层 2023 年初,Python 侧 LangChain 已经热闹非凡,Java 这边还在各自调 OpenAI 的 HTTP。我们团队想给内部系统接个问答能力,结果每个项目都自己封装一套 OkHttp 调用,模型一换全部重写。Spring 社区开始孵化一个叫 Spr
LLM 进了核心链路,黑盒就太危险 工单助手上线后,运营反馈"有时候答非所问"。但 LLM 调用对我们来说是个黑盒:不知道每次花了多少 token、耗时多少、模型返回了啥。更糟的是出了错没法归因。我参照传统可观测性,给 LLM 调用也接上了 Trace、Token 统计和效果评估三件套,才算把这层黑
给内部文档做个能问答的机器人 公司几百份技术文档散在 Wiki,搜起来费劲——关键词搜只能匹配字面,问"怎么处理订单超时"搜不到"订单 30 分钟未支付自动关单"的那段。我想用 RAG(检索增强生成)做个问答,让模型"先查资料再回答"。2023 年初这套链路在 Java 侧得自己拼,没有现成框架,正
LLM 调用账单太吓人 工单助手每天上万次调用 GPT,账单一个月涨到三千刀。财务找过来时我才认真看数据:大量 query 语义相近("怎么退货""退货流程""我要退钱"),答案其实一致,却每次都花 token 去问模型。用 Redis Stack 的向量检索做"语义缓存",把相似问题直接命中缓存,
半夜被内存告警叫醒 Redis 实例内存从 4G 一夜之间冲到 14G,触发了 maxmemory 限制开始淘汰 key,部分缓存击穿打到数据库,数据库 CPU 跟着飙到 90%。我登录上去按几个维度逐一排查,过程比想象的有条理。Redis 内存暴涨不是玄学,按固定顺序查基本能覆盖绝大多数情况。 先
内存曲线像极了漏水的水龙头 订单服务上线两周,Old 区内存从 1.2G 缓慢爬到 3.8G,Full GC 后也只回一点,没真正回落。不是突崩,是慢性失血。这种"缓增长"最容易被忽视,因为单次看都正常,直到某天 Old 区满了频繁 Full GC,接口全抖。我用多次 dump 对比把它揪出来,过程
ThreadLocal 在虚拟线程时代水土不服 我们的链路追踪 ID 一直用 ThreadLocal 传。切到虚拟线程后,一个请求一个虚拟线程,数量可能上百万,ThreadLocal 的哈希表跟着膨胀,而且线程复用导致上下文串台——上一个请求的 traceId 漏到了下一个。Java 21 的预览特
背景:一个 RAG 需求把选型问题拍到了脸上 三月初产品提了个需求:把过去三年积攒的技术工单做成内部知识库,让用户用自然语言提问。核心就一步——向量相似度检索。团队当时在 Milvus、PGVector、Redis 三套方案里反复横跳,谁也说服不了谁。我干脆拉了一台 16C32G 的机器,把三套都跑
不想为了监控拖垮生产 之前用 VisualVM 连生产抓采样,JMX 一开 CPU 就飘,GC 行为都变了,抓到的数据还不可信。后来发现 JDK 11 起的 JFR(Java Flight Recorder)开销极低,而且 JDK 14 起的 Event Streaming 能实时订阅事件,不用等
定时任务从 Quartz 搬出来的契机 老系统用 Quartz 集群,任务一多就出现重复触发,两台机器各跑一遍,数据算重了还得手工修。排查发现是 Quartz 的数据库锁在高峰期没兜住。今年做调度中台,我在 XXL-JOB 和 Elastic-Job 之间选,两者都能解决分布式场景,但设计取向不同,
想给搜索加上"语义" 我们的商品搜索一直靠关键词匹配,用户搜"适合送妈妈的礼物"这种长尾 query 基本搜不到,因为标题里没有这几个字。运营天天抱怨转化差。ES 8 增强了 dense_vector 和 kNN 检索,我试着把商品标题做成向量塞进去,让语义相近的也能召回,点击率明显好转。这里把建模
为了启动快,走上 GraalVM 原生镜像 FaaS 场景下单实例冷启动 4 秒太慢,用户第一次请求要等很久。我们想用 GraalVM 把订单服务编译成原生镜像,目标启动 50ms 内。Spring Boot 3 的 AOT 引擎能提前做大部分 Bean 的初始化分析,理论上开箱即用。可一上来就卡在
等到了 Spring Boot 3.2 的虚拟线程开关 Spring Boot 3.2 把虚拟线程集成做进了自动配置,一个属性就能让 Tomcat 用虚拟线程处理请求。我在 3.2 RC 阶段就拉下来试了,把订单查询接口从平台线程池切过去,吞吐数据很说明问题。不过 RC 阶段 API 还有微调,正式
一次全量上线引发的事故 三个月前我们直接全量发了订单服务 v2,结果一个新分支的序列化逻辑和旧版不兼容,老客户端解不出字段,半小时 rollback 了,期间丢了几十笔订单的回调。复盘会上被喷得不轻。痛定思痛,我搭了一套灰度发布体系,核心四件事:流量染色、网关路由、数据兼容、回滚机制。这套跑顺之后,
等了两年的正式版 JDK 21 在 9 月正式 GA,虚拟线程(Project Loom)终于从预览转正。作为常年和线程池、异步回调搏斗的人,我第一时间把内部一个 IO 密集的采集服务迁了过去。结果不算惊艳到颠覆,但确实把"一个请求一个线程"这种直观写法重新变可行了,迁移成本也比预期低。这里把原理、