<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>系统设计 | 杨劲松 - Java后端 / AI应用开发工程师</title><link>https://1byteone.github.io/tags/%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/</link><atom:link href="https://1byteone.github.io/tags/%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/index.xml" rel="self" type="application/rss+xml"/><description>系统设计</description><generator>HugoBlox Kit (https://hugoblox.com)</generator><language>zh-Hans</language><lastBuildDate>Fri, 21 Aug 2026 00:00:00 +0000</lastBuildDate><image><url>https://1byteone.github.io/media/icon_hu_1c0e9cb08cfb822a.png</url><title>系统设计</title><link>https://1byteone.github.io/tags/%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/</link></image><item><title>生产级 MySQL 高并发架构：缓存、读写分离与分片</title><link>https://1byteone.github.io/blog/mysql-high-concurrency-architecture/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate><guid>https://1byteone.github.io/blog/mysql-high-concurrency-architecture/</guid><description>&lt;p&gt;&lt;em&gt;上图：Production MySQL High-Concurrency Architecture 白板图；重点不是罗列名词，而是把一次真实请求如何穿过系统、在哪些边界失败画清楚。&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="为什么要从场景理解这张图"&gt;为什么要从场景理解这张图&lt;/h2&gt;
&lt;p&gt;这张图围绕“A feed service handles a hot tenant by caching reads, routing writes to the master, and testing restore before launch.”展开。学习 Production MySQL High-Concurrency Architecture 时，不能只记住组件名称：要能说明输入从哪里来、状态由谁持有、哪个组件承担失败、以及如何用指标证明系统仍然健康。白板中的箭头对应代码边界，红色感叹号对应需要显式处理的风险。&lt;/p&gt;
&lt;h2 id="逐层拆解"&gt;逐层拆解&lt;/h2&gt;
&lt;p&gt;主流程是：&lt;strong&gt;Client → Pool → Cache / Master / Replicas → Backup&lt;/strong&gt;。前半段是请求或数据的进入路径，后半段是运行时、存储或执行结果。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;边界契约&lt;/strong&gt;：先确定输入、输出和错误结构；不要让隐式类型、未校验参数或共享可变状态穿透多层。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;核心机制&lt;/strong&gt;：Cache-aside → read cache, write source；Master → writes + binlog。这些机制决定延迟、吞吐和可测试性。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;资源与状态&lt;/strong&gt;：Replicas → read scaling with lag awareness；Sharding → user_0 … user_N。生产系统必须说明资源何时创建、何时释放，以及状态是否可恢复。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;失败路径&lt;/strong&gt;：Slow Query → EXPLAIN → index tuning；必要时再结合 &lt;strong&gt;Backup → restore drill, not just backup files&lt;/strong&gt; 做降级、重试或回滚。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="一个可落地的最小实现"&gt;一个可落地的最小实现&lt;/h2&gt;
&lt;p&gt;下面的片段只展示边界，不代表完整业务。它的价值在于把“可以替换、可以测试、可以观测”的位置固定下来。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;read: Redis → Replica → Master fallback
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;write: idempotency → Master → binlog / event
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在真实项目中，应把外部依赖封装在 adapter 或 repository 中；业务层只依赖稳定接口。这样本地测试可以使用 fake，压测可以替换慢依赖，线上故障也更容易定位。&lt;/p&gt;
&lt;h2 id="场景中的工程决策"&gt;场景中的工程决策&lt;/h2&gt;
&lt;p&gt;以白板右侧的生产场景为例：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;先保护依赖&lt;/strong&gt;：连接池、线程池、并发信号量或缓存都要有上限，不能用无限队列掩盖下游过载。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;再保证正确性&lt;/strong&gt;：幂等键、事务边界、版本号、锁或 schema 校验至少要有一种明确机制，避免重试带来重复写入。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;最后优化性能&lt;/strong&gt;：先用 trace、慢查询、GC pause、队列长度、p99 延迟等数据定位，再选择索引、缓存、批处理或并发策略。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;让故障可恢复&lt;/strong&gt;：超时、重试、限流、熔断、回滚和告警必须能在演练中被验证，而不是只写在文档里。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="常见误区"&gt;常见误区&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;只画成功路径，没有画超时、空数据、拒绝、回滚或副本延迟。&lt;/li&gt;
&lt;li&gt;把框架默认行为当成业务契约，升级依赖后才发现边界改变。&lt;/li&gt;
&lt;li&gt;用“加机器”替代测量，忽略连接池、锁竞争、慢 SQL、对象分配或事件循环阻塞。&lt;/li&gt;
&lt;li&gt;将日志当作唯一观测手段，缺少指标、trace、采样和敏感数据脱敏。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="生产检查清单"&gt;生产检查清单&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; 输入、输出和错误响应有明确 schema&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; 外部调用设置 timeout、retry 上限、rate limit 和 fallback&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; 资源池有容量、排队和拒绝指标&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; 关键状态有幂等、事务或恢复策略&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; 日志、metrics、trace 可关联同一个 request id&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; 用接近生产的数据做回归、压测和故障演练&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="总结"&gt;总结&lt;/h2&gt;
&lt;p&gt;真正掌握这张白板图，不是能背出每个框的定义，而是能从一次具体请求出发，解释每个箭头的输入输出、每个风险的处置方式，以及上线后用什么信号判断系统需要改进。&lt;/p&gt;</description></item><item><title>生产级 Spring Boot 架构：可观测的服务边界</title><link>https://1byteone.github.io/blog/spring-boot-production-architecture/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate><guid>https://1byteone.github.io/blog/spring-boot-production-architecture/</guid><description>&lt;p&gt;&lt;em&gt;上图：Production Spring Boot Architecture 白板图；重点不是罗列名词，而是把一次真实请求如何穿过系统、在哪些边界失败画清楚。&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="为什么要从场景理解这张图"&gt;为什么要从场景理解这张图&lt;/h2&gt;
&lt;p&gt;这张图围绕“A flash-sale service protects the database with cache, bounded writes, idempotency, and asynchronous inventory events.”展开。学习 Production Spring Boot Architecture 时，不能只记住组件名称：要能说明输入从哪里来、状态由谁持有、哪个组件承担失败、以及如何用指标证明系统仍然健康。白板中的箭头对应代码边界，红色感叹号对应需要显式处理的风险。&lt;/p&gt;
&lt;h2 id="逐层拆解"&gt;逐层拆解&lt;/h2&gt;
&lt;p&gt;主流程是：&lt;strong&gt;Gateway → Service → Cache / DB / MQ → Observability&lt;/strong&gt;。前半段是请求或数据的进入路径，后半段是运行时、存储或执行结果。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;边界契约&lt;/strong&gt;：先确定输入、输出和错误结构；不要让隐式类型、未校验参数或共享可变状态穿透多层。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;核心机制&lt;/strong&gt;：Nginx / Gateway → auth + rate limit；Service → idempotency + transaction。这些机制决定延迟、吞吐和可测试性。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;资源与状态&lt;/strong&gt;：Redis → cache-aside with TTL；MySQL → source of truth。生产系统必须说明资源何时创建、何时释放，以及状态是否可恢复。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;失败路径&lt;/strong&gt;：RocketMQ → async side effects；必要时再结合 &lt;strong&gt;Metrics + Logs + Traces → feedback loop&lt;/strong&gt; 做降级、重试或回滚。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="一个可落地的最小实现"&gt;一个可落地的最小实现&lt;/h2&gt;
&lt;p&gt;下面的片段只展示边界，不代表完整业务。它的价值在于把“可以替换、可以测试、可以观测”的位置固定下来。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;request → idempotency → transaction → outbox event
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; → Redis / MySQL / MQ → trace + metrics
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在真实项目中，应把外部依赖封装在 adapter 或 repository 中；业务层只依赖稳定接口。这样本地测试可以使用 fake，压测可以替换慢依赖，线上故障也更容易定位。&lt;/p&gt;
&lt;h2 id="场景中的工程决策"&gt;场景中的工程决策&lt;/h2&gt;
&lt;p&gt;以白板右侧的生产场景为例：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;先保护依赖&lt;/strong&gt;：连接池、线程池、并发信号量或缓存都要有上限，不能用无限队列掩盖下游过载。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;再保证正确性&lt;/strong&gt;：幂等键、事务边界、版本号、锁或 schema 校验至少要有一种明确机制，避免重试带来重复写入。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;最后优化性能&lt;/strong&gt;：先用 trace、慢查询、GC pause、队列长度、p99 延迟等数据定位，再选择索引、缓存、批处理或并发策略。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;让故障可恢复&lt;/strong&gt;：超时、重试、限流、熔断、回滚和告警必须能在演练中被验证，而不是只写在文档里。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="常见误区"&gt;常见误区&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;只画成功路径，没有画超时、空数据、拒绝、回滚或副本延迟。&lt;/li&gt;
&lt;li&gt;把框架默认行为当成业务契约，升级依赖后才发现边界改变。&lt;/li&gt;
&lt;li&gt;用“加机器”替代测量，忽略连接池、锁竞争、慢 SQL、对象分配或事件循环阻塞。&lt;/li&gt;
&lt;li&gt;将日志当作唯一观测手段，缺少指标、trace、采样和敏感数据脱敏。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="生产检查清单"&gt;生产检查清单&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; 输入、输出和错误响应有明确 schema&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; 外部调用设置 timeout、retry 上限、rate limit 和 fallback&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; 资源池有容量、排队和拒绝指标&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; 关键状态有幂等、事务或恢复策略&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; 日志、metrics、trace 可关联同一个 request id&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; 用接近生产的数据做回归、压测和故障演练&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="总结"&gt;总结&lt;/h2&gt;
&lt;p&gt;真正掌握这张白板图，不是能背出每个框的定义，而是能从一次具体请求出发，解释每个箭头的输入输出、每个风险的处置方式，以及上线后用什么信号判断系统需要改进。&lt;/p&gt;</description></item></channel></rss>