<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[ppandss1的博客]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/ppandss1</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; ppandss1]]></copyright><item><title><![CDATA[AI 读了十万份文档，为什么还可能答错？聊聊 RAG、知识图谱和 LightRAG]]></title><link>https://blog.youkuaiyun.com/ppandss1/article/details/167388247</link><guid>https://blog.youkuaiyun.com/ppandss1/article/details/167388247</guid><author>ppandss1</author><pubDate>Fri, 09 Oct 2026 15:21:37 +0800</pubDate><description><![CDATA[因此一套组合可以是，Docling 解析文档，LightRAG 负责 Chunk 与图谱索引，BGE-M3 负责向量化，Qwen 或 DeepSeek 一类 LLM 负责关系抽取及问答，PostgreSQL 和 pgvector 负责存储。让大模型判断每个段落的主题边界，理论上很灵活，代价是额外的推理费用、处理时延，以及每次切分结果不一定完全一致。创建图谱时，LightRAG 通常先处理 Chunk，再调用 LLM 从其中抽取实体和关系，尝试归并重复实体，保留与来源文本的关联，然后把抽取结果写入图谱存储。]]></description><category></category></item><item><title><![CDATA[AI Coding 的第一步，是先想清楚你在干什么]]></title><link>https://blog.youkuaiyun.com/ppandss1/article/details/166580150</link><guid>https://blog.youkuaiyun.com/ppandss1/article/details/166580150</guid><author>ppandss1</author><pubDate>Thu, 24 Sep 2026 11:26:50 +0800</pubDate><description><![CDATA[新功能开发最容易犯的错误，是需求刚有一个雏形，就直接让 AI 开始写代码。现实中，很多开发者并没有专业产品经理长期配合，需求最初往往只有一句模糊的想法，例如“我想做一个 AI 自动生成研报的功能”或者“我想给现有系统加一个智能搜索”。这种情况下，正式进入开发之前，应该先把产品意图聊清楚。我更倾向于把这一阶段理解成“AI 产品经理”。它不只是帮你生成一份 PRD，而是通过连续追问，把用户是谁、要解决什么问题、核心场景是什么、边界在哪里这些内容逐渐收敛。PRD 可以是写出来的，也可以是聊出来的。]]></description><category></category></item><item><title><![CDATA[Redisson 分布式锁的底层原理，面试官听完都点头了]]></title><link>https://blog.youkuaiyun.com/ppandss1/article/details/163109988</link><guid>https://blog.youkuaiyun.com/ppandss1/article/details/163109988</guid><author>ppandss1</author><pubDate>Wed, 22 Jul 2026 16:53:33 +0800</pubDate><description><![CDATA[对比维度默认 RedissonLockRedLockRedis 节点单 Master（+Slave）多个独立 Master一致性保证最终一致性多数一致性Master 宕机可能丢失锁大多数节点健康即可性能高（1 次写）低（N/2+1 次写 + 网络开销）适用场景大多数业务金融、资损敏感场景很多人把 Redisson 默认实现和 RedLock 混为一谈，面试时一说到"主从一致"就说"用 RedLock"。实际上RedissonLock 默认不保证主从一致。]]></description><category></category></item><item><title><![CDATA[一个秒杀就把 MySQL 打挂了？我用 Redis + 异步削峰扛住了 100 倍流量]]></title><link>https://blog.youkuaiyun.com/ppandss1/article/details/163102011</link><guid>https://blog.youkuaiyun.com/ppandss1/article/details/163102011</guid><author>ppandss1</author><pubDate>Wed, 22 Jul 2026 11:16:07 +0800</pubDate><description><![CDATA[不要把 MySQL 当秒杀引擎。MySQL 的行锁和磁盘 IO 决定了它不适合做"热点写"，让它做最终落库就够了。Redis + LUA 原子脚本做资格校验，把 3 万 QPS 降维到几百 TPS 的 DB 写入，延迟从 8 秒降到 12 毫秒。**异步削峰（阻塞队列 + 单线程消费者）**让数据库写入速率变得可控，完全避免死锁和雪崩。最终一致性 > 强一致性。秒杀不是银行转账，短暂的缓存和数据库不一致可以接受，但数据绝对不能丢。]]></description><category></category></item><item><title><![CDATA[别再手动封装List当队列了！Redis Stream消息队列，原理+实战一篇讲透]]></title><link>https://blog.youkuaiyun.com/ppandss1/article/details/163101898</link><guid>https://blog.youkuaiyun.com/ppandss1/article/details/163101898</guid><author>ppandss1</author><pubDate>Wed, 22 Jul 2026 11:13:55 +0800</pubDate><description><![CDATA[对比维度默认 RedissonLockRedLockRedis 节点单 Master（+Slave）多个独立 Master一致性保证最终一致性多数一致性Master 宕机可能丢失锁大多数节点健康即可性能高（1 次写）低（N/2+1 次写 + 网络开销）适用场景大多数业务金融、资损敏感场景很多人把 Redisson 默认实现和 RedLock 混为一谈，面试时一说到"主从一致"就说"用 RedLock"。实际上RedissonLock 默认不保证主从一致。]]></description><category></category></item><item><title><![CDATA[生产环境分布式锁踩坑实录：从 synchronized 失效到 Redlock，我画了 3 张图终于讲透了]]></title><link>https://blog.youkuaiyun.com/ppandss1/article/details/163071475</link><guid>https://blog.youkuaiyun.com/ppandss1/article/details/163071475</guid><author>ppandss1</author><pubDate>Tue, 21 Jul 2026 11:07:44 +0800</pubDate><description><![CDATA[生产环境分布式锁实现方案对比 本文系统梳理了分布式锁的演进过程，从单机锁失效问题到Redis分布式锁的4个版本演进，最终给出三种主流实现方案的对比： 核心演进点： synchronized失效原因（JVM进程隔离） Redis分布式锁演进（NX+TTL→唯一ID→Lua原子性→看门狗续期） 主从架构下的Redlock方案 Redis/ZK/MySQL三种方案对比 方案对比： 对比维度 Redis（Redisson） ZooKeeper（Curator） MySQL 性能 最高（内存操作） 中等（ZK写性能一]]></description><category></category></item><item><title><![CDATA[“乐观锁还是悲观锁“，三张图终于把多线程并发说透了]]></title><link>https://blog.youkuaiyun.com/ppandss1/article/details/163050028</link><guid>https://blog.youkuaiyun.com/ppandss1/article/details/163050028</guid><author>ppandss1</author><pubDate>Mon, 20 Jul 2026 16:20:24 +0800</pubDate><description><![CDATA[选锁第一原则：看写冲突概率。高 → 悲观锁；低 → 乐观锁synchronized 不是洪水猛兽：JDK 1.6 后有锁升级，低竞争下开销很小CAS 不是业务校验：它是 CPU 原子指令，保证读-比较-写不可分割一人一单最佳实践：数据库唯一约束比应用层锁更简单可靠生产环境常用组合：Redis 预扣库存（乐观 Lua）+ 数据库兜底（版本号）+ 唯一约束防重复。]]></description><category></category></item><item><title><![CDATA[缓存穿透、击穿、雪崩？别再死记硬背了，一文讲透Redis缓存三大难题]]></title><link>https://blog.youkuaiyun.com/ppandss1/article/details/163014985</link><guid>https://blog.youkuaiyun.com/ppandss1/article/details/163014985</guid><author>ppandss1</author><pubDate>Sun, 19 Jul 2026 11:12:18 +0800</pubDate><description><![CDATA[fill:#333;important;important;fill:none;color:#333;color:#333;important;fill:none;fill:#333;height:1em;低高业务场景一致性要求?Redis 内存淘汰更新 DB删除缓存下次读时回写配置 maxmemory-policy缓存更新：低一致性用 Redis 内存淘汰，高一致性用 Cache Aside（写 DB 删缓存）缓存穿透：优先缓存空值（0 成本改动），id 范围固定时上布隆过滤器。]]></description><category></category></item><item><title><![CDATA[别再背八股文了！Redis 缓存穿透、缓存雪崩？先搞懂这 30 行查询代码再说]]></title><link>https://blog.youkuaiyun.com/ppandss1/article/details/162998672</link><guid>https://blog.youkuaiyun.com/ppandss1/article/details/162998672</guid><author>ppandss1</author><pubDate>Sat, 18 Jul 2026 16:30:42 +0800</pubDate><description><![CDATA[文章摘要 本文通过剖析一段30行的Redis缓存查询代码，揭示了缓存穿透防护的核心原理。作者从实践出发，逐行拆解代码逻辑，包括Redis key命名规范、缓存命中判断、JSON序列化与反序列化等关键点。文章特别强调理解这段基础代码（Cache-Aside Pattern）比死记硬背"缓存穿透/雪崩"等概念更重要，并用时序图清晰展示了"先查缓存→未命中查DB→回写Redis"的完整流程。通过实际代码演示，帮助开发者真正掌握缓存机制的本质实现。]]></description><category></category></item><item><title><![CDATA[面试官问“登陆拦截器为啥写两个“？我给他画了张图，他当场说过了]]></title><link>https://blog.youkuaiyun.com/ppandss1/article/details/162944310</link><guid>https://blog.youkuaiyun.com/ppandss1/article/details/162944310</guid><author>ppandss1</author><pubDate>Thu, 16 Jul 2026 19:39:25 +0800</pubDate><description><![CDATA[前端存 token 到 localStorage，通过 Authorization 请求头发送——不走 cookie，自己控制Redis + UUID 方案的核心优势是服务端可控——可以踢人、可以活跃续期、可以实时变更用户信息ThreadLocal 是线程级别的变量隔离——拦截器把用户信息写进去，整个请求周期都能读"活跃用户永不过期"靠的是 RefreshTokenInterceptor——它拦截所有路径，永远放行。]]></description><category></category></item><item><title><![CDATA[Spring Boot 拦截器，我把学习踩坑过程画了张图]]></title><link>https://blog.youkuaiyun.com/ppandss1/article/details/162936925</link><guid>https://blog.youkuaiyun.com/ppandss1/article/details/162936925</guid><author>ppandss1</author><pubDate>Thu, 16 Jul 2026 14:38:17 +0800</pubDate><description><![CDATA[拦截器的位置：夹在 HandlerMapping 和 Controller 之间，比 Filter 更靠近业务层，适合做基于"用户"的校验。从 Session 只取必要字段，不要整坨 User 对象到处传——既防止泄漏，也避免 Session 序列化膨胀。ThreadLocal 必须 paired with remove()，在 afterCompletion() 里清理，这不是锦上添花，是必须做。配置拦截路径时别漏了静态资源放行——否则网页样式全挂，排查起来很匪夷所思。进阶思考。]]></description><category></category></item><item><title><![CDATA[Entity、DTO、Session 不就是三个「数据容器」吗？错！一个储物柜比喻让你彻底搞懂]]></title><link>https://blog.youkuaiyun.com/ppandss1/article/details/162879562</link><guid>https://blog.youkuaiyun.com/ppandss1/article/details/162879562</guid><author>ppandss1</author><pubDate>Tue, 14 Jul 2026 17:54:14 +0800</pubDate><description><![CDATA[Entity 是数据库的镜子——1:1 映射表结构，包含所有字段和 ORM 注解。它的生命周期属于 DAO 层。DTO 是接口的契约——只包含你想暴露的字段，与服务/控制器层同生命周期。它是你跟客户端之间的约定。Session 是用户的储物柜——它本身不是「数据」而是一个KV 存储空间。可以把 DTO 放进去，用来跨请求保存用户状态。最佳实践：DB 层用 Entity -> Service 层转成 DTO -> 需要跨请求的 DTO 塞进 Session。不要存 Entity，不要混用职责。]]></description><category></category></item><item><title><![CDATA[Service 和 Impl 到底谁写代码？写给对着分层结构发懵的小白]]></title><link>https://blog.youkuaiyun.com/ppandss1/article/details/162879133</link><guid>https://blog.youkuaiyun.com/ppandss1/article/details/162879133</guid><author>ppandss1</author><pubDate>Tue, 14 Jul 2026 17:36:00 +0800</pubDate><description><![CDATA[你盯着IDE里那一排包名——controller、service、mapper、entity——光标在UserController里闪了半天。你明明知道要"根据手机号查一个用户"。就这么简单一个需求，但你发现不知道该往哪写。“写在Controller里？应该不行吧…教程说Controller很薄。那Service里写？那为什么Service还有一个接口？我直接写一个类不行吗？impl又是什么东西？这些问题，教程里不会专门停下来跟你讲。你顺着视频敲一遍能跑，但换你自己写一个新接口，就懵了。]]></description><category></category></item><item><title><![CDATA[JavaWeb从0到1-DAY11.1-MyBatis入门（ii）]]></title><link>https://blog.youkuaiyun.com/ppandss1/article/details/161601948</link><guid>https://blog.youkuaiyun.com/ppandss1/article/details/161601948</guid><author>ppandss1</author><pubDate>Mon, 01 Jun 2026 22:07:40 +0800</pubDate><description><![CDATA[注解 XML 两把刀”。注解适合简单增删改查，XML 适合复杂 SQL——实际项目混合使用。#{}是默认选择、安全可靠，${}只在特殊场景用且严防注入。XML 映射靠三规则精准对应。DML 返回值判断操作是否生效。@Param帮多参数起名，建议始终写。配置文件开日志、配 XML 路径、开驼峰映射，省去大量麻烦。]]></description><category></category></item><item><title><![CDATA[写了 266 行 SKILL.md，Codex 死活不认——揪出 UTF-8 BOM 这个隐形杀手]]></title><link>https://blog.youkuaiyun.com/ppandss1/article/details/161520389</link><guid>https://blog.youkuaiyun.com/ppandss1/article/details/161520389</guid><author>ppandss1</author><pubDate>Fri, 29 May 2026 16:50:23 +0800</pubDate><description><![CDATA[团队规范要求所有 commit message 遵循格式。每次git commit都要手写，烦得不行。于是你写了 200 多行 SKILL.md，做了一个skill——输一段改动描述，自动生成规范的 commit message。写好、测试、放到，重启 Codex。敲下$git-commit "修了登录页token过期不刷新的bug"。Codex 回你一句「未找到该 skill」。你以为是触发词没写对，又把 description 里的关键词改了三版——gitcommit提交全塞进去。依旧不认。]]></description><category></category></item><item><title><![CDATA[Codex 用 DeepSeek 模型无法识图？一招接入千问 VL，让 AI 秒懂你的截图]]></title><link>https://blog.youkuaiyun.com/ppandss1/article/details/161517850</link><guid>https://blog.youkuaiyun.com/ppandss1/article/details/161517850</guid><author>ppandss1</author><pubDate>Fri, 29 May 2026 15:01:43 +0800</pubDate><description><![CDATA[某天你正在用 Codex，后端报了一长串异常，你懒得复制粘贴，直接截图甩给 AI。结果它回复：“我暂时看不到你发的图片内容——图片标签里没有可读取的路径。你能描述一下图片里是什么内容吗？你忍住摔键盘的冲动，老老实实打字描述。然后你又发了第二张、第三张截图，AI 直接开始"失忆"——上下文爆了，token 超限，前面的对话全白费。这不是你的问题，是模型的问题。DeepSeek-V4-Pro、DeepSeek-V4-Flash 这些模型天生没有 Vision 能力——它们只能读文字，看不懂图。]]></description><category></category></item><item><title><![CDATA[JavaWeb从0到1-DAY11-MyBatis入门]]></title><link>https://blog.youkuaiyun.com/ppandss1/article/details/161516915</link><guid>https://blog.youkuaiyun.com/ppandss1/article/details/161516915</guid><author>ppandss1</author><pubDate>Fri, 29 May 2026 14:19:54 +0800</pubDate><description><![CDATA[MyBatis 是对 JDBC 的封装，解决硬编码、繁琐、资源浪费三大痛点。核心用法只需三步：在 application.properties 配好数据库连接 → 写一个带 @Mapper 的接口并标注 SQL → 用 @SpringBootTest 编写测试验证。底层靠动态代理让接口"自动拥有"实现类，靠连接池让数据库连接高效复用。掌握这章的五步入门流程，后面学增删改查就都是同一个套路了。]]></description><category></category></item><item><title><![CDATA[JavaWeb从0到1-DAY10-JDBC]]></title><link>https://blog.youkuaiyun.com/ppandss1/article/details/161321226</link><guid>https://blog.youkuaiyun.com/ppandss1/article/details/161321226</guid><author>ppandss1</author><pubDate>Fri, 22 May 2026 17:37:31 +0800</pubDate><description><![CDATA[JDBC 是 Java 操作数据库的底层基石。获取连接 → 发 SQL → 处理结果。记住六步编程框架，永远用 PreparedStatement，上线必配连接池，多表操作开事务。但实际开发中你不会手写这些——MyBatis、JPA 等框架已经帮你封装好了，它们底层调用的正是 JDBC。学好 JDBC 的意义不在于手写代码，而在于：当框架出问题时你知道底层发生了什么，看得懂报错，调得了性能。]]></description><category></category></item><item><title><![CDATA[JavaWeb从0到1-DAY9-三层架构、IOC 与 DI]]></title><link>https://blog.youkuaiyun.com/ppandss1/article/details/161229424</link><guid>https://blog.youkuaiyun.com/ppandss1/article/details/161229424</guid><author>ppandss1</author><pubDate>Tue, 19 May 2026 17:20:44 +0800</pubDate><description><![CDATA[Controller接收请求并响应数据，Service处理业务逻辑，Dao负责数据访问。三层架构体现了单一职责原则，也让代码更容易扩展和复用。IOC 把对象创建和管理交给容器，DI 让容器把依赖对象注入进来。@Autowired默认按类型注入，如果同类型 Bean 有多个，可以用@Primary@Qualifier或@Resource解决。]]></description><category></category></item><item><title><![CDATA[JavaWeb从0到1-DAY8-前后端交互（基础）]]></title><link>https://blog.youkuaiyun.com/ppandss1/article/details/161202700</link><guid>https://blog.youkuaiyun.com/ppandss1/article/details/161202700</guid><author>ppandss1</author><pubDate>Mon, 18 May 2026 22:19:38 +0800</pubDate><description><![CDATA[表示把/list请求交给当前方法处理。表示按逗号拆分字符串。表示把字符串转成整数。表示按指定格式把字符串转成时间对象。表示把集合中的每个元素转换后，再收集成新的集合。这一章的核心是理解前后端交互：前端通过 HTTP 请求地址，后端通过找到方法并执行。或决定返回值会作为响应数据返回，而不是当成页面名。后端可以读取资源文件或数据库，把数据封装成 Java 对象集合，再由 Spring 转成 JSON。前端最终拿到 JSON 数据并渲染页面。]]></description><category></category></item></channel></rss>