fix(eslint): reduce warnings in GitHub Actions deployment

- Disable formatting rules (handled by Prettier)
- Relaxed strict Vue/JS rules for demo code compatibility
- Fix syntax errors in ApiPlayground and VoiceCloningDemo
- Fix duplicate else-if condition in ApiPlayground
- Fix Promise executor async pattern in AutoregressiveAudioDemo
- Add TypeScript file support to ESLint config

Warnings reduced from 295 to 251 problems.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
sanbuphy
2026-02-18 17:38:10 +08:00
parent 8b01686e68
commit 0eba9e87e9
456 changed files with 28450 additions and 9677 deletions
@@ -13,16 +13,29 @@
<div class="architecture-flow">
<div class="flow-layer user">
<div class="layer-label">用户请求</div>
<div class="request-icon">👤</div>
<div class="layer-label">
用户请求
</div>
<div class="request-icon">
👤
</div>
</div>
<div class="arrow"></div>
<div class="arrow">
</div>
<div class="flow-layer cache" :class="{ active: currentLayer === 'cache' }">
<div class="layer-label">缓存层 (Cache)</div>
<div
class="flow-layer cache"
:class="{ active: currentLayer === 'cache' }"
>
<div class="layer-label">
缓存层 (Cache)
</div>
<div class="cache-box">
<div class="cache-icon"></div>
<div class="cache-icon">
</div>
<div class="cache-stats">
<div>命中率: {{ hitRate }}%</div>
<div>响应时间: ~1ms</div>
@@ -31,16 +44,23 @@
</div>
<div class="arrow">
<span v-if="showMiss" class="miss-text">未命中</span>
<span
v-if="showMiss"
class="miss-text"
>未命中</span>
</div>
<div
class="flow-layer database"
:class="{ active: currentLayer === 'database' }"
>
<div class="layer-label">数据库层 (Database)</div>
<div class="layer-label">
数据库层 (Database)
</div>
<div class="database-box">
<div class="database-icon">🗄</div>
<div class="database-icon">
🗄
</div>
<div class="database-stats">
<div>响应时间: ~50ms</div>
<div>持久化存储</div>
@@ -50,21 +70,37 @@
</div>
<div class="comparison">
<div class="comparison-title">访问速度对比</div>
<div class="comparison-title">
访问速度对比
</div>
<div class="speed-bars">
<div class="speed-item">
<div class="label">缓存命中</div>
<div class="bar-container">
<div class="bar fast" :style="{ width: '5%' }"></div>
<div class="label">
缓存命中
</div>
<div class="bar-container">
<div
class="bar fast"
:style="{ width: '5%' }"
/>
</div>
<div class="time">
~1ms
</div>
<div class="time">~1ms</div>
</div>
<div class="speed-item">
<div class="label">数据库查询</div>
<div class="bar-container">
<div class="bar slow" :style="{ width: '100%' }"></div>
<div class="label">
数据库查询
</div>
<div class="bar-container">
<div
class="bar slow"
:style="{ width: '100%' }"
/>
</div>
<div class="time">
~50ms
</div>
<div class="time">~50ms</div>
</div>
</div>
<div class="conclusion">
@@ -73,8 +109,16 @@
</div>
<div class="interactive-demo">
<button class="demo-btn" @click="simulateRequest">模拟请求</button>
<div class="demo-result" v-if="lastResult">
<button
class="demo-btn"
@click="simulateRequest"
>
模拟请求
</button>
<div
v-if="lastResult"
class="demo-result"
>
<span :class="{ hit: lastResult.hit, miss: !lastResult.hit }">
{{ lastResult.hit ? '✅ 缓存命中' : '❌ 缓存未命中,访问数据库' }}
</span>
@@ -13,13 +13,22 @@
<div class="architecture-diagram">
<div class="layer user-layer">
<div class="layer-icon">👤</div>
<div class="layer-label">用户请求</div>
<div class="layer-icon">
👤
</div>
<div class="layer-label">
用户请求
</div>
</div>
<div class="arrow-down"></div>
<div class="arrow-down">
</div>
<div class="layer cdn-layer" :class="{ active: activeLayer === 'cdn' }">
<div
class="layer cdn-layer"
:class="{ active: activeLayer === 'cdn' }"
>
<div class="layer-header">
<span class="icon">🌐</span>
<span class="layer-name">CDN 缓存</span>
@@ -40,9 +49,14 @@
</div>
</div>
<div class="arrow-down"></div>
<div class="arrow-down">
</div>
<div class="layer local-layer" :class="{ active: activeLayer === 'local' }">
<div
class="layer local-layer"
:class="{ active: activeLayer === 'local' }"
>
<div class="layer-header">
<span class="icon">💻</span>
<span class="layer-name">本地缓存</span>
@@ -63,9 +77,14 @@
</div>
</div>
<div class="arrow-down"></div>
<div class="arrow-down">
</div>
<div class="layer distributed-layer" :class="{ active: activeLayer === 'distributed' }">
<div
class="layer distributed-layer"
:class="{ active: activeLayer === 'distributed' }"
>
<div class="layer-header">
<span class="icon">🗄</span>
<span class="layer-name">分布式缓存</span>
@@ -86,7 +105,9 @@
</div>
</div>
<div class="arrow-down"></div>
<div class="arrow-down">
</div>
<div class="layer database-layer">
<div class="layer-header">
@@ -26,7 +26,10 @@
<div class="layer-stats">
<div class="stat">
<span class="stat-label">速度</span>
<span class="stat-value" :class="layer.speedClass">{{ layer.speed }}</span>
<span
class="stat-value"
:class="layer.speedClass"
>{{ layer.speed }}</span>
</div>
<div class="stat">
<span class="stat-label">容量</span>
@@ -37,36 +40,81 @@
<span class="stat-value">{{ layer.cost }}</span>
</div>
</div>
<div v-if="index < layers.length - 1" class="arrow"></div>
<div
v-if="index < layers.length - 1"
class="arrow"
>
</div>
</div>
</div>
<div class="data-flow">
<div class="flow-title">数据流动演示</div>
<div class="flow-title">
数据流动演示
</div>
<div class="flow-steps">
<div class="flow-step" :class="{ active: flowStep >= 1 }">
<div class="step-number">1</div>
<div class="step-text">查询 L1 缓存</div>
<div class="step-time">~1ns</div>
<div
class="flow-step"
:class="{ active: flowStep >= 1 }"
>
<div class="step-number">
1
</div>
<div class="step-text">
查询 L1 缓存
</div>
<div class="step-time">
~1ns
</div>
</div>
<div class="flow-arrow"></div>
<div class="flow-step" :class="{ active: flowStep >= 2 }">
<div class="step-number">2</div>
<div class="step-text">未命中 L2</div>
<div class="step-time">~10ns</div>
<div class="flow-arrow">
</div>
<div class="flow-arrow"></div>
<div class="flow-step" :class="{ active: flowStep >= 3 }">
<div class="step-number">3</div>
<div class="step-text">未命中 L3</div>
<div class="step-time">~100ns</div>
<div
class="flow-step"
:class="{ active: flowStep >= 2 }"
>
<div class="step-number">
2
</div>
<div class="step-text">
未命中 L2
</div>
<div class="step-time">
~10ns
</div>
</div>
<div class="flow-arrow">
</div>
<div
class="flow-step"
:class="{ active: flowStep >= 3 }"
>
<div class="step-number">
3
</div>
<div class="step-text">
未命中 L3
</div>
<div class="step-time">
~100ns
</div>
</div>
</div>
<button class="simulate-btn" @click="simulateFlow">模拟数据查找</button>
<button
class="simulate-btn"
@click="simulateFlow"
>
模拟数据查找
</button>
</div>
<div class="comparison-table">
<div class="table-title">各层级对比</div>
<div class="table-title">
各层级对比
</div>
<table>
<thead>
<tr>
@@ -77,7 +125,11 @@
</tr>
</thead>
<tbody>
<tr v-for="layer in layers" :key="layer.id" :class="{ active: activeLayer === layer.id }">
<tr
v-for="layer in layers"
:key="layer.id"
:class="{ active: activeLayer === layer.id }"
>
<td>{{ layer.name }}</td>
<td>{{ layer.speed }}</td>
<td>{{ layer.capacity }}</td>
@@ -5,8 +5,12 @@
<template>
<div class="cache-lifecycle-demo">
<div class="header">
<div class="title">缓存生命周期演示</div>
<div class="subtitle">观察缓存条目从创建到淘汰的完整过程</div>
<div class="title">
缓存生命周期演示
</div>
<div class="subtitle">
观察缓存条目从创建到淘汰的完整过程
</div>
</div>
<div class="cache-container">
@@ -33,24 +37,26 @@
}"
>
<div class="entry-header">
<div class="entry-id">{{ entry.key }}</div>
<div class="entry-id">
{{ entry.key }}
</div>
<div class="entry-status">
<span v-if="entry.status === 'new'" class="status-badge new"
>NEW</span
>
<span v-if="entry.status === 'hit'" class="status-badge hit"
>HIT</span
>
<span
v-if="entry.status === 'new'"
class="status-badge new"
>NEW</span>
<span
v-if="entry.status === 'hit'"
class="status-badge hit"
>HIT</span>
<span
v-if="entry.status === 'expiring'"
class="status-badge expiring"
>EXPIRING</span
>
>EXPIRING</span>
<span
v-if="entry.status === 'evicting'"
class="status-badge evicting"
>EVICTING</span
>
>EVICTING</span>
</div>
</div>
<div class="entry-ttl">
@@ -58,9 +64,11 @@
<div
class="ttl-fill"
:style="{ width: entry.ttlPercent + '%' }"
></div>
/>
</div>
<div class="ttl-text">
TTL: {{ entry.ttl }}s
</div>
<div class="ttl-text">TTL: {{ entry.ttl }}s</div>
</div>
<div class="entry-meta">
<span>命中: {{ entry.hits }}</span>
@@ -73,8 +81,18 @@
<div class="controls">
<div class="control-group">
<label>操作</label>
<button class="action-btn read" @click="readData">读取数据</button>
<button class="action-btn write" @click="writeData">写入新数据</button>
<button
class="action-btn read"
@click="readData"
>
读取数据
</button>
<button
class="action-btn write"
@click="writeData"
>
写入新数据
</button>
</div>
<div class="control-group">
@@ -90,7 +108,9 @@
</div>
<div class="timeline">
<div class="timeline-title">事件时间线</div>
<div class="timeline-title">
事件时间线
</div>
<div class="timeline-events">
<div
v-for="(event, index) in events"
@@ -98,7 +118,9 @@
class="event"
:class="event.type"
>
<div class="event-time">{{ event.time }}</div>
<div class="event-time">
{{ event.time }}
</div>
<div class="event-content">
<span class="event-icon">{{ event.icon }}</span>
<span class="event-text">{{ event.text }}</span>
@@ -109,19 +131,19 @@
<div class="legend">
<div class="legend-item">
<span class="legend-color new"></span>
<span class="legend-color new" />
<span>新写入</span>
</div>
<div class="legend-item">
<span class="legend-color hit"></span>
<span class="legend-color hit" />
<span>缓存命中</span>
</div>
<div class="legend-item">
<span class="legend-color expiring"></span>
<span class="legend-color expiring" />
<span>即将过期</span>
</div>
<div class="legend-item">
<span class="legend-color evicting"></span>
<span class="legend-color evicting" />
<span>淘汰中</span>
</div>
</div>
@@ -13,22 +13,36 @@
<div class="metrics-grid">
<div class="metric-card hit-rate">
<div class="metric-icon">🎯</div>
<div class="metric-icon">
🎯
</div>
<div class="metric-content">
<div class="metric-label">命中率</div>
<div class="metric-value" :class="getHitRateClass">
<div class="metric-label">
命中率
</div>
<div
class="metric-value"
:class="getHitRateClass"
>
{{ hitRate }}%
</div>
<div class="metric-trend" :class="trendClass">
<div
class="metric-trend"
:class="trendClass"
>
{{ trendIcon }} {{ trendValue }}%
</div>
</div>
</div>
<div class="metric-card response-time">
<div class="metric-icon"></div>
<div class="metric-icon">
</div>
<div class="metric-content">
<div class="metric-label">平均响应时间</div>
<div class="metric-label">
平均响应时间
</div>
<div class="metric-value">
{{ avgResponseTime }}ms
</div>
@@ -39,9 +53,13 @@
</div>
<div class="metric-card cache-size">
<div class="metric-icon">📦</div>
<div class="metric-icon">
📦
</div>
<div class="metric-content">
<div class="metric-label">缓存使用量</div>
<div class="metric-label">
缓存使用量
</div>
<div class="metric-value">
{{ usedSize }}MB
</div>
@@ -52,7 +70,7 @@
width: `${sizeUsagePercent}%`,
backgroundColor: getSizeBarColor
}"
></div>
/>
</div>
<div class="metric-sub">
{{ usedSize }}MB / {{ maxSize }}MB
@@ -61,9 +79,13 @@
</div>
<div class="metric-card requests">
<div class="metric-icon">📊</div>
<div class="metric-icon">
📊
</div>
<div class="metric-content">
<div class="metric-label">总请求数</div>
<div class="metric-label">
总请求数
</div>
<div class="metric-value">
{{ totalRequests.toLocaleString() }}
</div>
@@ -77,7 +99,12 @@
<div class="request-log">
<div class="log-header">
<span>📋 请求日志</span>
<button class="clear-btn" @click="clearLog">清空</button>
<button
class="clear-btn"
@click="clearLog"
>
清空
</button>
</div>
<div class="log-list">
<transition-group name="log-item">
@@ -94,20 +121,32 @@
<span class="log-latency">{{ log.latency }}ms</span>
</div>
</transition-group>
<div v-if="requestLogs.length === 0" class="empty-log">
<div
v-if="requestLogs.length === 0"
class="empty-log"
>
暂无请求记录点击下方按钮发送请求
</div>
</div>
</div>
<div class="control-panel">
<button class="action-btn" @click="simulateRequest">
<button
class="action-btn"
@click="simulateRequest"
>
🎲 模拟请求
</button>
<button class="action-btn" @click="simulateBurst">
<button
class="action-btn"
@click="simulateBurst"
>
🚀 连续请求 (10)
</button>
<button class="action-btn outline" @click="resetMetrics">
<button
class="action-btn outline"
@click="resetMetrics"
>
重置指标
</button>
</div>
@@ -25,21 +25,30 @@
</div>
<div class="pattern-content">
<div v-if="activePattern === 'cache-aside'" class="pattern-detail">
<div
v-if="activePattern === 'cache-aside'"
class="pattern-detail"
>
<div class="pattern-header">
<h3>Cache-Aside (旁路缓存)</h3>
<p class="pattern-desc">最常用的模式应用代码直接控制缓存</p>
<p class="pattern-desc">
最常用的模式应用代码直接控制缓存
</p>
</div>
<div class="flow-diagram">
<div class="flow-step read">
<div class="step-icon">📖</div>
<div class="step-icon">
📖
</div>
<div class="step-content">
<strong>读取</strong>先查缓存 没有就查数据库 写入缓存
</div>
</div>
<div class="flow-step write">
<div class="step-icon"></div>
<div class="step-icon">
</div>
<div class="step-content">
<strong>更新</strong>先更新数据库 <span class="highlight">删除</span>缓存不是更新
</div>
@@ -48,33 +57,54 @@
<div class="pros-cons">
<div class="pros">
<div class="list-title"> 优点</div>
<div class="list-item">灵活可精细控制</div>
<div class="list-item">适合大多数场景</div>
<div class="list-title">
优点
</div>
<div class="list-item">
灵活可精细控制
</div>
<div class="list-item">
适合大多数场景
</div>
</div>
<div class="cons">
<div class="list-title"> 缺点</div>
<div class="list-item">代码复杂度较高</div>
<div class="list-item">需要手动维护一致性</div>
<div class="list-title">
缺点
</div>
<div class="list-item">
代码复杂度较高
</div>
<div class="list-item">
需要手动维护一致性
</div>
</div>
</div>
</div>
<div v-if="activePattern === 'read-through'" class="pattern-detail">
<div
v-if="activePattern === 'read-through'"
class="pattern-detail"
>
<div class="pattern-header">
<h3>Read-Through (读穿透)</h3>
<p class="pattern-desc">缓存库负责从数据库加载数据</p>
<p class="pattern-desc">
缓存库负责从数据库加载数据
</p>
</div>
<div class="flow-diagram">
<div class="flow-step">
<div class="step-icon">📖</div>
<div class="step-icon">
📖
</div>
<div class="step-content">
<strong>读取</strong>应用只调 cache.get()缓存库负责查数据库
</div>
</div>
<div class="flow-step">
<div class="step-icon"></div>
<div class="step-icon">
</div>
<div class="step-content">
<strong>写入</strong>通常与 Write-Through 配合同步写缓存和数据库
</div>
@@ -83,33 +113,54 @@
<div class="pros-cons">
<div class="pros">
<div class="list-title"> 优点</div>
<div class="list-item">代码简洁</div>
<div class="list-item">一致性更好</div>
<div class="list-title">
优点
</div>
<div class="list-item">
代码简洁
</div>
<div class="list-item">
一致性更好
</div>
</div>
<div class="cons">
<div class="list-title"> 缺点</div>
<div class="list-item">需要专门的缓存库</div>
<div class="list-item">灵活性较低</div>
<div class="list-title">
缺点
</div>
<div class="list-item">
需要专门的缓存库
</div>
<div class="list-item">
灵活性较低
</div>
</div>
</div>
</div>
<div v-if="activePattern === 'write-behind'" class="pattern-detail">
<div
v-if="activePattern === 'write-behind'"
class="pattern-detail"
>
<div class="pattern-header">
<h3>Write-Behind (异步写回)</h3>
<p class="pattern-desc">写入时只写缓存异步批量写数据库</p>
<p class="pattern-desc">
写入时只写缓存异步批量写数据库
</p>
</div>
<div class="flow-diagram">
<div class="flow-step">
<div class="step-icon"></div>
<div class="step-icon">
</div>
<div class="step-content">
<strong>写入</strong>立即写缓存 异步批量写数据库
</div>
</div>
<div class="flow-step">
<div class="step-icon"></div>
<div class="step-icon">
</div>
<div class="step-content">
<strong>风险</strong>缓存崩溃会导致数据丢失
</div>
@@ -118,21 +169,35 @@
<div class="pros-cons">
<div class="pros">
<div class="list-title"> 优点</div>
<div class="list-item">写入极快</div>
<div class="list-item">适合写多场景</div>
<div class="list-title">
优点
</div>
<div class="list-item">
写入极快
</div>
<div class="list-item">
适合写多场景
</div>
</div>
<div class="cons">
<div class="list-title"> 缺点</div>
<div class="list-item">可能丢失数据</div>
<div class="list-item">一致性差</div>
<div class="list-title">
缺点
</div>
<div class="list-item">
可能丢失数据
</div>
<div class="list-item">
一致性差
</div>
</div>
</div>
</div>
</div>
<div class="comparison-table">
<div class="table-title">三种模式对比</div>
<div class="table-title">
三种模式对比
</div>
<table>
<thead>
<tr>
@@ -5,8 +5,12 @@
<template>
<div class="cache-patterns-demo">
<div class="header">
<div class="title">缓存模式 (Caching Patterns)</div>
<div class="subtitle">理解不同缓存读写模式的工作原理</div>
<div class="title">
缓存模式 (Caching Patterns)
</div>
<div class="subtitle">
理解不同缓存读写模式的工作原理
</div>
</div>
<div class="pattern-selector">
@@ -23,10 +27,17 @@
<div class="pattern-content">
<!-- Cache-Aside -->
<div v-if="activePattern === 'cache-aside'" class="pattern-detail">
<div
v-if="activePattern === 'cache-aside'"
class="pattern-detail"
>
<div class="description">
<div class="pattern-title">Cache-Aside (旁路缓存)</div>
<div class="pattern-subtitle">最常用的模式由应用代码控制缓存</div>
<div class="pattern-title">
Cache-Aside (旁路缓存)
</div>
<div class="pattern-subtitle">
最常用的模式由应用代码控制缓存
</div>
<div class="pattern-points">
<div class="point">
<span class="icon">📖</span>
@@ -37,50 +48,93 @@
<div class="point">
<span class="icon"></span>
<div>
<strong>更新</strong
>先更新数据库然后<strong>删除</strong>缓存不是更新
<strong>更新</strong>先更新数据库然后<strong>删除</strong>缓存不是更新
</div>
</div>
</div>
</div>
<div class="diagram">
<div class="diagram-title">读取流程</div>
<div class="diagram-title">
读取流程
</div>
<div class="flow-chart">
<div class="flow-step" :class="{ active: flowStep >= 1 }">
<div class="step-number">1</div>
<div class="step-text">查询缓存</div>
<div
class="flow-step"
:class="{ active: flowStep >= 1 }"
>
<div class="step-number">
1
</div>
<div class="step-text">
查询缓存
</div>
</div>
<div class="flow-arrow">
</div>
<div class="flow-arrow"></div>
<div class="flow-decision">
<div class="decision-label">命中?</div>
<div class="decision-label">
命中?
</div>
<div class="decision-branches">
<div
class="branch yes"
:class="{ active: flowStep >= 2 && cacheHit }"
>
<div class="branch-label"></div>
<div class="branch-result"> 返回数据</div>
<div class="branch-label">
</div>
<div class="branch-result">
返回数据
</div>
</div>
<div
class="branch no"
:class="{ active: flowStep >= 2 && !cacheHit }"
>
<div class="branch-label"></div>
<div class="branch-label">
</div>
<div class="branch-steps">
<div class="flow-step" :class="{ active: flowStep >= 3 }">
<div class="step-number">2</div>
<div class="step-text">查询数据库</div>
<div
class="flow-step"
:class="{ active: flowStep >= 3 }"
>
<div class="step-number">
2
</div>
<div class="step-text">
查询数据库
</div>
</div>
<div class="flow-arrow"></div>
<div class="flow-step" :class="{ active: flowStep >= 4 }">
<div class="step-number">3</div>
<div class="step-text">写入缓存</div>
<div class="flow-arrow">
</div>
<div class="flow-arrow"></div>
<div class="flow-step" :class="{ active: flowStep >= 5 }">
<div class="step-number">4</div>
<div class="step-text">返回数据</div>
<div
class="flow-step"
:class="{ active: flowStep >= 4 }"
>
<div class="step-number">
3
</div>
<div class="step-text">
写入缓存
</div>
</div>
<div class="flow-arrow">
</div>
<div
class="flow-step"
:class="{ active: flowStep >= 5 }"
>
<div class="step-number">
4
</div>
<div class="step-text">
返回数据
</div>
</div>
</div>
</div>
@@ -91,20 +145,25 @@
<div class="demo-controls">
<button
class="demo-btn"
@click="simulateCacheAside"
:disabled="simulating"
@click="simulateCacheAside"
>
{{ simulating ? '模拟中...' : '模拟读取' }}
</button>
<label class="checkbox">
<input type="checkbox" v-model="cacheHit" />
<input
v-model="cacheHit"
type="checkbox"
>
缓存命中
</label>
</div>
</div>
<div class="code-example">
<div class="code-title">代码示例</div>
<div class="code-title">
代码示例
</div>
<pre class="code-block"><code>// Cache-Aside 模式
def get_user(user_id):
# 1. 查缓存
@@ -130,9 +189,14 @@ def update_user(user_id, data):
</div>
<!-- Read-Through -->
<div v-if="activePattern === 'read-through'" class="pattern-detail">
<div
v-if="activePattern === 'read-through'"
class="pattern-detail"
>
<div class="description">
<div class="pattern-title">Read-Through / Write-Through</div>
<div class="pattern-title">
Read-Through / Write-Through
</div>
<div class="pattern-subtitle">
由缓存库负责与数据库交互应用只和缓存打交道
</div>
@@ -153,12 +217,18 @@ def update_user(user_id, data):
</div>
<div class="diagram">
<div class="diagram-title">架构对比</div>
<div class="diagram-title">
架构对比
</div>
<div class="architecture-comparison">
<div class="arch-block">
<div class="arch-title">Cache-Aside</div>
<div class="arch-title">
Cache-Aside
</div>
<div class="arch-flow">
<div class="flow-box app">应用</div>
<div class="flow-box app">
应用
</div>
<div class="flow-arrows">
<div> 缓存</div>
<div> 数据库</div>
@@ -166,20 +236,28 @@ def update_user(user_id, data):
</div>
</div>
<div class="arch-block">
<div class="arch-title">Read-Through</div>
<div class="arch-title">
Read-Through
</div>
<div class="arch-flow">
<div class="flow-box app">应用</div>
<div class="flow-box app">
应用
</div>
<div class="flow-arrows">
<div> 缓存库</div>
</div>
<div class="flow-box cache">缓存库 数据库</div>
<div class="flow-box cache">
缓存库 数据库
</div>
</div>
</div>
</div>
</div>
<div class="code-example">
<div class="code-title">代码示例</div>
<div class="code-title">
代码示例
</div>
<pre class="code-block"><code>// Read-Through 模式(代码更简洁)
def get_user(user_id):
# 缓存库自动处理数据库查询
@@ -194,10 +272,17 @@ def update_user(user_id, data):
</div>
<!-- Write-Behind -->
<div v-if="activePattern === 'write-behind'" class="pattern-detail">
<div
v-if="activePattern === 'write-behind'"
class="pattern-detail"
>
<div class="description">
<div class="pattern-title">Write-Behind (异步写回)</div>
<div class="pattern-subtitle">写入时只写缓存异步批量写数据库</div>
<div class="pattern-title">
Write-Behind (异步写回)
</div>
<div class="pattern-subtitle">
写入时只写缓存异步批量写数据库
</div>
<div class="pattern-points">
<div class="point">
<span class="icon"></span>
@@ -212,42 +297,71 @@ def update_user(user_id, data):
<div class="point">
<span class="icon">🎯</span>
<div>
<strong>适用</strong
>秒杀系统点赞数浏览量可接受少量丢失
<strong>适用</strong>秒杀系统点赞数浏览量可接受少量丢失
</div>
</div>
</div>
</div>
<div class="diagram">
<div class="diagram-title">写入流程</div>
<div class="diagram-title">
写入流程
</div>
<div class="flow-chart">
<div class="flow-step">
<div class="step-number">1</div>
<div class="step-text">写入缓存</div>
<div class="step-time"> ~1ms</div>
<div class="step-number">
1
</div>
<div class="step-text">
写入缓存
</div>
<div class="step-time">
~1ms
</div>
</div>
<div class="flow-arrow">
</div>
<div class="flow-arrow"></div>
<div class="flow-step">
<div class="step-number">2</div>
<div class="step-text">立即返回</div>
<div class="step-number">
2
</div>
<div class="step-text">
立即返回
</div>
</div>
<div class="flow-arrow">
</div>
<div class="flow-arrow"></div>
<div class="flow-step pending">
<div class="step-number">3</div>
<div class="step-text">异步批量写数据库</div>
<div class="step-time">🕐 后台执行</div>
<div class="step-number">
3
</div>
<div class="step-text">
异步批量写数据库
</div>
<div class="step-time">
🕐 后台执行
</div>
</div>
</div>
<div class="demo-controls">
<button class="demo-btn" @click="simulateWriteBehind">
<button
class="demo-btn"
@click="simulateWriteBehind"
>
模拟批量写入
</button>
</div>
<div class="write-queue" v-if="writeQueue.length > 0">
<div class="queue-title">待写入队列</div>
<div
v-if="writeQueue.length > 0"
class="write-queue"
>
<div class="queue-title">
待写入队列
</div>
<div class="queue-items">
<div
v-for="(item, index) in writeQueue"
@@ -263,7 +377,9 @@ def update_user(user_id, data):
</div>
<div class="code-example">
<div class="code-title">代码示例</div>
<div class="code-title">
代码示例
</div>
<pre class="code-block"><code>// Write-Behind 模式
def update_counter(post_id):
# 1. 立即更新缓存极快
@@ -283,7 +399,9 @@ def update_counter(post_id):
</div>
<div class="pattern-comparison">
<div class="comparison-title">模式对比</div>
<div class="comparison-title">
模式对比
</div>
<table class="comparison-table">
<thead>
<tr>
@@ -5,8 +5,12 @@
<template>
<div class="cache-problems-demo">
<div class="header">
<div class="title">缓存的三大问题</div>
<div class="subtitle">穿透击穿雪崩的场景与解决方案</div>
<div class="title">
缓存的三大问题
</div>
<div class="subtitle">
穿透击穿雪崩的场景与解决方案
</div>
</div>
<div class="problem-selector">
@@ -24,9 +28,14 @@
<div class="problem-content">
<!-- 缓存穿透 -->
<div v-if="activeProblem === 'penetration'" class="problem-detail">
<div
v-if="activeProblem === 'penetration'"
class="problem-detail"
>
<div class="problem-intro">
<div class="intro-title">什么是缓存穿透</div>
<div class="intro-title">
什么是缓存穿透
</div>
<div class="intro-text">
查询一个<strong>不存在的数据</strong>如恶意请求
id=-1缓存没有数据库也没有 导致每次请求都直接打到数据库
@@ -34,51 +43,78 @@
</div>
<div class="problem-scenario">
<div class="scenario-title">场景模拟</div>
<div class="scenario-title">
场景模拟
</div>
<div class="scenario-diagram">
<div class="flow-item request">
<div class="flow-icon">🔥</div>
<div class="flow-text">请求 id=-999</div>
<div class="flow-icon">
🔥
</div>
<div class="flow-text">
请求 id=-999
</div>
</div>
<div class="flow-arrow"></div>
<div class="flow-item cache" :class="{ miss: true }">
<div class="flow-icon"></div>
<div class="flow-text">缓存未命中</div>
<div class="flow-arrow">
</div>
<div
class="flow-item cache"
:class="{ miss: true }"
>
<div class="flow-icon">
</div>
<div class="flow-text">
缓存未命中
</div>
</div>
<div class="flow-arrow">
</div>
<div class="flow-arrow"></div>
<div
class="flow-item database"
:class="{ overloaded: dbPressure >= 80 }"
>
<div class="flow-icon">🗄</div>
<div class="flow-text">数据库查询不存在</div>
<div class="flow-icon">
🗄
</div>
<div class="flow-text">
数据库查询不存在
</div>
</div>
</div>
<div class="controls">
<button
class="attack-btn"
@click="simulatePenetration"
:disabled="simulating"
@click="simulatePenetration"
>
{{ simulating ? '攻击中...' : '模拟恶意攻击' }}
</button>
</div>
<div class="pressure-meter">
<div class="meter-label">数据库压力</div>
<div class="meter-label">
数据库压力
</div>
<div class="meter-bar">
<div
class="meter-fill"
:style="{ width: dbPressure + '%' }"
></div>
/>
</div>
<div class="meter-value">
{{ dbPressure }}%
</div>
<div class="meter-value">{{ dbPressure }}%</div>
</div>
</div>
<div class="solutions">
<div class="solutions-title">解决方案</div>
<div class="solutions-title">
解决方案
</div>
<div class="solution-list">
<div class="solution-item">
<div class="solution-header">
@@ -87,7 +123,7 @@
</div>
<div class="solution-desc">
在缓存前加一层过滤器快速判断"这个 id 肯定不存在"
<br />
<br>
<span class="note">100% 判断不存在但可能有误判</span>
</div>
</div>
@@ -105,25 +141,34 @@
</div>
<!-- 缓存击穿 -->
<div v-if="activeProblem === 'breakdown'" class="problem-detail">
<div
v-if="activeProblem === 'breakdown'"
class="problem-detail"
>
<div class="problem-intro">
<div class="intro-title">什么是缓存击穿</div>
<div class="intro-title">
什么是缓存击穿
</div>
<div class="intro-text">
某个<strong>热点数据</strong>过期如微博热搜瞬间几百万请求同时打到数据库
</div>
</div>
<div class="problem-scenario">
<div class="scenario-title">场景模拟</div>
<div class="scenario-title">
场景模拟
</div>
<div class="hotkey-scenario">
<div class="hotkey-badge">
🔥 热点数据
<br />
<br>
<span class="key">user:12345</span>
</div>
<div class="concurrent-requests">
<div class="requests-title">并发请求</div>
<div class="requests-title">
并发请求
</div>
<div class="requests-container">
<div
v-for="(req, index) in concurrentRequests"
@@ -131,23 +176,34 @@
class="request-item"
:class="req.status"
>
<div class="request-id">请求 {{ req.id }}</div>
<div class="request-status">{{ req.statusText }}</div>
<div class="request-id">
请求 {{ req.id }}
</div>
<div class="request-status">
{{ req.statusText }}
</div>
</div>
</div>
</div>
<div class="mutex-visual" v-if="showMutex">
<div class="mutex-badge">🔒 互斥锁</div>
<div class="mutex-text">只有一个线程能查数据库</div>
<div
v-if="showMutex"
class="mutex-visual"
>
<div class="mutex-badge">
🔒 互斥锁
</div>
<div class="mutex-text">
只有一个线程能查数据库
</div>
</div>
</div>
<div class="controls">
<button
class="attack-btn"
@click="simulateBreakdown"
:disabled="simulating"
@click="simulateBreakdown"
>
{{ simulating ? '模拟中...' : '模拟热点过期' }}
</button>
@@ -155,7 +211,9 @@
</div>
<div class="solutions">
<div class="solutions-title">解决方案</div>
<div class="solutions-title">
解决方案
</div>
<div class="solution-list">
<div class="solution-item">
<div class="solution-header">
@@ -164,7 +222,7 @@
</div>
<div class="solution-desc">
只允许一个线程查数据库其他线程等待
<br />
<br>
<span class="note">优点简单缺点阻塞其他请求</span>
</div>
</div>
@@ -175,10 +233,8 @@
</div>
<div class="solution-desc">
不设置 TTL而是在 value 里存一个过期时间字段
<br />
<span class="note"
>查询时发现"逻辑过期"异步更新缓存同时返回旧数据</span
>
<br>
<span class="note">查询时发现"逻辑过期"异步更新缓存同时返回旧数据</span>
</div>
</div>
</div>
@@ -186,9 +242,14 @@
</div>
<!-- 缓存雪崩 -->
<div v-if="activeProblem === 'avalanche'" class="problem-detail">
<div
v-if="activeProblem === 'avalanche'"
class="problem-detail"
>
<div class="problem-intro">
<div class="intro-title">什么是缓存雪崩</div>
<div class="intro-title">
什么是缓存雪崩
</div>
<div class="intro-text">
大量缓存<strong>同时过期</strong>如系统重启后所有缓存都在
00:00:00 过期 数据库瞬间被打爆
@@ -196,7 +257,9 @@
</div>
<div class="problem-scenario">
<div class="scenario-title">场景模拟</div>
<div class="scenario-title">
场景模拟
</div>
<div class="avalanche-visual">
<div class="cache-items">
<div
@@ -205,38 +268,61 @@
class="cache-item"
:class="{ expired: item.expired }"
>
<div class="item-key">{{ item.key }}</div>
<div class="item-ttl">TTL: {{ item.ttl }}s</div>
<div class="item-key">
{{ item.key }}
</div>
<div class="item-ttl">
TTL: {{ item.ttl }}s
</div>
</div>
</div>
<div class="mass-explosion" v-if="massExplosion">
<div class="explosion-icon">💥</div>
<div class="explosion-text">同时过期</div>
<div
v-if="massExplosion"
class="mass-explosion"
>
<div class="explosion-icon">
💥
</div>
<div class="explosion-text">
同时过期
</div>
</div>
<div class="db-overload" :class="{ critical: dbPressure >= 90 }">
<div class="db-icon">🗄</div>
<div class="db-status">数据库负载: {{ dbPressure }}%</div>
<div
class="db-overload"
:class="{ critical: dbPressure >= 90 }"
>
<div class="db-icon">
🗄
</div>
<div class="db-status">
数据库负载: {{ dbPressure }}%
</div>
</div>
</div>
<div class="controls">
<button
class="attack-btn"
@click="simulateAvalanche"
:disabled="simulating"
@click="simulateAvalanche"
>
{{ simulating ? '模拟中...' : '模拟缓存雪崩' }}
</button>
<button class="solution-btn" @click="applyRandomTTL">
<button
class="solution-btn"
@click="applyRandomTTL"
>
应用解决方案随机 TTL
</button>
</div>
</div>
<div class="solutions">
<div class="solutions-title">解决方案</div>
<div class="solutions-title">
解决方案
</div>
<div class="solution-list">
<div class="solution-item">
<div class="solution-header">
@@ -245,10 +331,8 @@
</div>
<div class="solution-desc">
避免同时过期TTL 加上随机值
<br />
<span class="code"
>ttl = 600 + random.randint(-60, 60) # 600 ± 60 </span
>
<br>
<span class="code">ttl = 600 + random.randint(-60, 60) # 600 ± 60 </span>
</div>
</div>
<div class="solution-item">
@@ -258,10 +342,8 @@
</div>
<div class="solution-desc">
系统启动时主动加载热点数据到缓存
<br />
<span class="note"
>使用定时任务提前刷新即将过期的热点数据</span
>
<br>
<span class="note">使用定时任务提前刷新即将过期的热点数据</span>
</div>
</div>
<div class="solution-item">
@@ -271,7 +353,7 @@
</div>
<div class="solution-desc">
当数据库压力过大时暂时停止更新缓存直接返回降级数据
<br />
<br>
<span class="note">"系统繁忙,请稍后再试"</span>
</div>
</div>
@@ -281,7 +363,9 @@
</div>
<div class="comparison-table">
<div class="table-title">三大问题对比</div>
<div class="table-title">
三大问题对比
</div>
<table class="problems-table">
<thead>
<tr>
@@ -3,10 +3,15 @@
<div class="demo-container">
<div class="demo-header">
<h4>{{ title }}</h4>
<p class="hint">{{ description }}</p>
<p class="hint">
{{ description }}
</p>
</div>
<div class="demo-content">
<el-alert type="info" :closable="false">
<el-alert
type="info"
:closable="false"
>
电商缓存架构演示组件占位符 - 待实现具体交互
</el-alert>
</div>
@@ -5,25 +5,41 @@
<template>
<div class="cache-comparison-demo">
<div class="header">
<div class="title">本地缓存 vs 分布式缓存</div>
<div class="subtitle">对比两种缓存架构的性能和特点</div>
<div class="title">
本地缓存 vs 分布式缓存
</div>
<div class="subtitle">
对比两种缓存架构的性能和特点
</div>
</div>
<div class="comparison-view">
<!-- Local Cache -->
<div class="cache-side local">
<div class="side-header">
<div class="title">本地缓存 (Local Cache)</div>
<div class="tag">进程内</div>
<div class="title">
本地缓存 (Local Cache)
</div>
<div class="tag">
进程内
</div>
</div>
<div class="architecture">
<div class="app-instance">
<div class="instance-label">应用实例 1</div>
<div class="instance-label">
应用实例 1
</div>
<div class="cache-box">
<div class="cache-label">缓存</div>
<div class="cache-label">
缓存
</div>
<div class="cache-data">
<div v-for="item in localCache1" :key="item" class="data-item">
<div
v-for="item in localCache1"
:key="item"
class="data-item"
>
{{ item }}
</div>
</div>
@@ -31,11 +47,19 @@
</div>
<div class="app-instance">
<div class="instance-label">应用实例 2</div>
<div class="instance-label">
应用实例 2
</div>
<div class="cache-box">
<div class="cache-label">缓存</div>
<div class="cache-label">
缓存
</div>
<div class="cache-data">
<div v-for="item in localCache2" :key="item" class="data-item">
<div
v-for="item in localCache2"
:key="item"
class="data-item"
>
{{ item }}
</div>
</div>
@@ -45,29 +69,53 @@
<div class="metrics">
<div class="metric">
<div class="metric-label">响应时间</div>
<div class="metric-value fast">~1 ms</div>
<div class="metric-label">
响应时间
</div>
<div class="metric-value fast">
~1 ms
</div>
</div>
<div class="metric">
<div class="metric-label">容量</div>
<div class="metric-value">~1 GB</div>
<div class="metric-label">
容量
</div>
<div class="metric-value">
~1 GB
</div>
</div>
<div class="metric">
<div class="metric-label">一致性</div>
<div class="metric-value warning"></div>
<div class="metric-label">
一致性
</div>
<div class="metric-value warning">
</div>
</div>
</div>
<div class="pros-cons">
<div class="pros">
<div class="list-title"> 优点</div>
<div class="list-item">极快无网络开销</div>
<div class="list-item">简单内存 Map</div>
<div class="list-title">
优点
</div>
<div class="list-item">
极快无网络开销
</div>
<div class="list-item">
简单内存 Map
</div>
</div>
<div class="cons">
<div class="list-title"> 缺点</div>
<div class="list-item">容量受限</div>
<div class="list-item">实例间不一致</div>
<div class="list-title">
缺点
</div>
<div class="list-item">
容量受限
</div>
<div class="list-item">
实例间不一致
</div>
</div>
</div>
</div>
@@ -75,33 +123,51 @@
<!-- Distributed Cache -->
<div class="cache-side distributed">
<div class="side-header">
<div class="title">分布式缓存 (Distributed Cache)</div>
<div class="tag">独立服务</div>
<div class="title">
分布式缓存 (Distributed Cache)
</div>
<div class="tag">
独立服务
</div>
</div>
<div class="architecture">
<div class="instances-row">
<div class="app-instance-small">
<div class="instance-label-small">实例 1</div>
<div class="instance-label-small">
实例 1
</div>
</div>
<div class="app-instance-small">
<div class="instance-label-small">实例 2</div>
<div class="instance-label-small">
实例 2
</div>
</div>
<div class="app-instance-small">
<div class="instance-label-small">实例 3</div>
<div class="instance-label-small">
实例 3
</div>
</div>
</div>
<div class="network-layer">
<div class="network-label">网络</div>
<div class="network-arrows"> </div>
<div class="network-label">
网络
</div>
<div class="network-arrows">
</div>
</div>
<div class="redis-cluster">
<div class="cluster-label">Redis 集群</div>
<div class="cluster-label">
Redis 集群
</div>
<div class="redis-nodes">
<div class="redis-node">
<div class="node-label">Node 1</div>
<div class="node-label">
Node 1
</div>
<div class="node-data">
<div
v-for="item in redisData1"
@@ -113,7 +179,9 @@
</div>
</div>
<div class="redis-node">
<div class="node-label">Node 2</div>
<div class="node-label">
Node 2
</div>
<div class="node-data">
<div
v-for="item in redisData2"
@@ -125,7 +193,9 @@
</div>
</div>
<div class="redis-node">
<div class="node-label">Node 3</div>
<div class="node-label">
Node 3
</div>
<div class="node-data">
<div
v-for="item in redisData3"
@@ -142,48 +212,96 @@
<div class="metrics">
<div class="metric">
<div class="metric-label">响应时间</div>
<div class="metric-value medium">~5 ms</div>
<div class="metric-label">
响应时间
</div>
<div class="metric-value medium">
~5 ms
</div>
</div>
<div class="metric">
<div class="metric-label">容量</div>
<div class="metric-value">~100 GB</div>
<div class="metric-label">
容量
</div>
<div class="metric-value">
~100 GB
</div>
</div>
<div class="metric">
<div class="metric-label">一致性</div>
<div class="metric-value good"></div>
<div class="metric-label">
一致性
</div>
<div class="metric-value good">
</div>
</div>
</div>
<div class="pros-cons">
<div class="pros">
<div class="list-title"> 优点</div>
<div class="list-item">容量可扩展</div>
<div class="list-item">全局共享</div>
<div class="list-title">
优点
</div>
<div class="list-item">
容量可扩展
</div>
<div class="list-item">
全局共享
</div>
</div>
<div class="cons">
<div class="list-title"> 缺点</div>
<div class="list-item">网络延迟</div>
<div class="list-item">需要维护</div>
<div class="list-title">
缺点
</div>
<div class="list-item">
网络延迟
</div>
<div class="list-item">
需要维护
</div>
</div>
</div>
</div>
</div>
<div class="interactive-demo">
<div class="demo-title">交互演示写入和读取数据</div>
<div class="demo-title">
交互演示写入和读取数据
</div>
<div class="demo-controls">
<button class="demo-btn" @click="simulateWrite">写入数据</button>
<button class="demo-btn secondary" @click="simulateRead">
<button
class="demo-btn"
@click="simulateWrite"
>
写入数据
</button>
<button
class="demo-btn secondary"
@click="simulateRead"
>
读取数据
</button>
<button class="demo-btn reset" @click="reset">重置</button>
<button
class="demo-btn reset"
@click="reset"
>
重置
</button>
</div>
<div class="demo-result" v-if="lastOperation">
<div class="result-icon">{{ lastOperation.icon }}</div>
<div class="result-text">{{ lastOperation.text }}</div>
<div class="result-detail">{{ lastOperation.detail }}</div>
<div
v-if="lastOperation"
class="demo-result"
>
<div class="result-icon">
{{ lastOperation.icon }}
</div>
<div class="result-text">
{{ lastOperation.text }}
</div>
<div class="result-detail">
{{ lastOperation.detail }}
</div>
</div>
</div>
</div>
@@ -5,8 +5,12 @@
<template>
<div class="locality-demo">
<div class="header">
<div class="title">局部性原理演示</div>
<div class="subtitle">理解缓存为什么有效</div>
<div class="title">
局部性原理演示
</div>
<div class="subtitle">
理解缓存为什么有效
</div>
</div>
<div class="tabs">
@@ -28,18 +32,20 @@
<div class="tab-content">
<!-- Temporal Locality -->
<div v-if="activeTab === 'temporal'" class="temporal-demo">
<div
v-if="activeTab === 'temporal'"
class="temporal-demo"
>
<div class="description">
<strong>时间局部性</strong
>如果你访问了某个数据未来很可能再次访问它
<br />
<span class="example"
>例子用户登录后每次请求都需要查询用户信息</span
>
<strong>时间局部性</strong>如果你访问了某个数据未来很可能再次访问它
<br>
<span class="example">例子用户登录后每次请求都需要查询用户信息</span>
</div>
<div class="timeline">
<div class="timeline-title">访问时间线</div>
<div class="timeline-title">
访问时间线
</div>
<div class="timeline-events">
<div
v-for="(event, index) in temporalEvents"
@@ -47,7 +53,9 @@
class="event"
:class="{ hit: event.hit, miss: !event.hit }"
>
<div class="event-time">{{ event.time }}</div>
<div class="event-time">
{{ event.time }}
</div>
<div class="event-action">
<span class="user-icon">👤</span>
<span>查询 user_{{ event.userId }}</span>
@@ -60,7 +68,9 @@
</div>
<div class="cache-state">
<div class="cache-title">当前缓存状态</div>
<div class="cache-title">
当前缓存状态
</div>
<div class="cache-items">
<div
v-for="item in cacheItems"
@@ -68,24 +78,32 @@
class="cache-item"
:class="{ active: item.active }"
>
<div class="item-id">{{ item.id }}</div>
<div class="item-hits">命中 {{ item.hits }} </div>
<div class="item-id">
{{ item.id }}
</div>
<div class="item-hits">
命中 {{ item.hits }}
</div>
</div>
</div>
</div>
</div>
<!-- Spatial Locality -->
<div v-if="activeTab === 'spatial'" class="spatial-demo">
<div
v-if="activeTab === 'spatial'"
class="spatial-demo"
>
<div class="description">
<strong>空间局部性</strong
>如果你访问了某个数据很可能访问它附近的数据
<br />
<strong>空间局部性</strong>如果你访问了某个数据很可能访问它附近的数据
<br>
<span class="example">例子浏览商品列表时通常会翻到下一页</span>
</div>
<div class="product-grid">
<div class="grid-title">商品浏览序列</div>
<div class="grid-title">
商品浏览序列
</div>
<div class="products">
<div
v-for="product in products"
@@ -97,7 +115,9 @@
current: product.current
}"
>
<div class="product-id">{{ product.id }}</div>
<div class="product-id">
{{ product.id }}
</div>
<div class="product-status">
<span v-if="product.current">👁 当前</span>
<span v-else-if="product.cached"> 已缓存</span>
@@ -109,14 +129,18 @@
<div class="spatial-explanation">
<div class="explanation-item">
<div class="icon">📊</div>
<div class="icon">
📊
</div>
<div class="text">
<strong>预取策略</strong>当你浏览第 5 个商品时系统自动将 6-8
预加载到缓存
</div>
</div>
<div class="explanation-item">
<div class="icon">🎯</div>
<div class="icon">
🎯
</div>
<div class="text">
<strong>命中率提升</strong>空间局部性让缓存命中率达到 70-90%
</div>
@@ -126,22 +150,44 @@
</div>
<div class="interactive-controls">
<button class="control-btn" @click="addEvent">添加访问事件</button>
<button class="control-btn secondary" @click="reset">重置</button>
<button
class="control-btn"
@click="addEvent"
>
添加访问事件
</button>
<button
class="control-btn secondary"
@click="reset"
>
重置
</button>
</div>
<div class="stats">
<div class="stat-item">
<div class="stat-label">总访问次数</div>
<div class="stat-value">{{ totalAccess }}</div>
<div class="stat-label">
总访问次数
</div>
<div class="stat-value">
{{ totalAccess }}
</div>
</div>
<div class="stat-item">
<div class="stat-label">缓存命中</div>
<div class="stat-value hit">{{ hitCount }}</div>
<div class="stat-label">
缓存命中
</div>
<div class="stat-value hit">
{{ hitCount }}
</div>
</div>
<div class="stat-item">
<div class="stat-label">命中率</div>
<div class="stat-value">{{ hitRate }}%</div>
<div class="stat-label">
命中率
</div>
<div class="stat-value">
{{ hitRate }}%
</div>
</div>
</div>
</div>
@@ -5,8 +5,12 @@
<template>
<div class="multi-level-cache-demo">
<div class="header">
<div class="title">多级缓存架构</div>
<div class="subtitle">每一层都是上一层的"保护伞"</div>
<div class="title">
多级缓存架构
</div>
<div class="subtitle">
每一层都是上一层的"保护伞"
</div>
</div>
<div class="cache-levels">
@@ -20,33 +24,53 @@
miss: level.status === 'miss'
}"
>
<div class="level-number">L{{ level.layer }}</div>
<div class="level-number">
L{{ level.layer }}
</div>
<div class="level-content">
<div class="level-header">
<div class="level-name">{{ level.name }}</div>
<div class="level-name">
{{ level.name }}
</div>
<div class="level-meta">
<span class="latency">{{ level.latency }}</span>
<span class="capacity">{{ level.capacity }}</span>
</div>
</div>
<div class="level-description">{{ level.description }}</div>
<div class="level-status" v-if="level.status">
<span v-if="level.status === 'hit'" class="status-badge hit"
> 命中</span
>
<span v-if="level.status === 'miss'" class="status-badge miss"
> 未命中</span
>
<div class="level-description">
{{ level.description }}
</div>
<div
v-if="level.status"
class="level-status"
>
<span
v-if="level.status === 'hit'"
class="status-badge hit"
> 命中</span>
<span
v-if="level.status === 'miss'"
class="status-badge miss"
> 未命中</span>
</div>
</div>
<div class="level-arrow" v-if="index < cacheLevels.length - 1"></div>
<div
v-if="index < cacheLevels.length - 1"
class="level-arrow"
>
</div>
</div>
</div>
<div class="controls">
<div class="control-group">
<label>请求数据</label>
<button class="request-btn" @click="makeRequest" :disabled="processing">
<button
class="request-btn"
:disabled="processing"
@click="makeRequest"
>
{{ processing ? '处理中...' : '发起请求' }}
</button>
</div>
@@ -55,18 +79,29 @@
<label>模拟场景</label>
<select
v-model="scenario"
@change="onScenarioChange"
class="scenario-select"
@change="onScenarioChange"
>
<option value="normal">正常访问 (70% 命中率)</option>
<option value="cold">冷启动 (0% 命中率)</option>
<option value="hot">热点数据 (95% 命中率)</option>
<option value="normal">
正常访问 (70% 命中率)
</option>
<option value="cold">
冷启动 (0% 命中率)
</option>
<option value="hot">
热点数据 (95% 命中率)
</option>
</select>
</div>
</div>
<div class="request-flow" v-if="requestHistory.length > 0">
<div class="flow-title">请求流程</div>
<div
v-if="requestHistory.length > 0"
class="request-flow"
>
<div class="flow-title">
请求流程
</div>
<div class="flow-timeline">
<div
v-for="(event, index) in requestHistory"
@@ -74,70 +109,96 @@
class="flow-event"
:class="event.type"
>
<div class="event-level">{{ event.level }}</div>
<div class="event-level">
{{ event.level }}
</div>
<div class="event-action">
<span class="event-icon">{{ event.icon }}</span>
<span class="event-text">{{ event.action }}</span>
</div>
<div class="event-time">{{ event.time }}ms</div>
<div class="event-time">
{{ event.time }}ms
</div>
</div>
</div>
</div>
<div class="statistics">
<div class="stat-card">
<div class="stat-label">总请求数</div>
<div class="stat-value">{{ stats.totalRequests }}</div>
<div class="stat-label">
总请求数
</div>
<div class="stat-value">
{{ stats.totalRequests }}
</div>
</div>
<div class="stat-card">
<div class="stat-label">缓存命中</div>
<div class="stat-value hit">{{ stats.cacheHits }}</div>
<div class="stat-label">
缓存命中
</div>
<div class="stat-value hit">
{{ stats.cacheHits }}
</div>
</div>
<div class="stat-card">
<div class="stat-label">命中率</div>
<div class="stat-value">{{ stats.hitRate }}%</div>
<div class="stat-label">
命中率
</div>
<div class="stat-value">
{{ stats.hitRate }}%
</div>
</div>
<div class="stat-card">
<div class="stat-label">平均响应时间</div>
<div class="stat-value">{{ stats.avgLatency }}ms</div>
<div class="stat-label">
平均响应时间
</div>
<div class="stat-value">
{{ stats.avgLatency }}ms
</div>
</div>
<div class="stat-card">
<div class="stat-label">数据库访问</div>
<div class="stat-value db">{{ stats.dbAccess }}</div>
<div class="stat-label">
数据库访问
</div>
<div class="stat-value db">
{{ stats.dbAccess }}
</div>
</div>
</div>
<div class="explanation">
<div class="explanation-title">多级缓存的优势</div>
<div class="explanation-title">
多级缓存的优势
</div>
<div class="explanation-grid">
<div class="explanation-item">
<div class="item-icon">🛡</div>
<div class="item-icon">
🛡
</div>
<div class="item-text">
<strong>逐级过滤</strong>
<br />
<span class="item-detail"
>每层过滤掉大部分请求最终到达数据库的可能只有 1%</span
>
<br>
<span class="item-detail">每层过滤掉大部分请求最终到达数据库的可能只有 1%</span>
</div>
</div>
<div class="explanation-item">
<div class="item-icon"></div>
<div class="item-icon">
</div>
<div class="item-text">
<strong>极速响应</strong>
<br />
<span class="item-detail"
>上层缓存命中时响应时间从 50ms 降至 0-10ms</span
>
<br>
<span class="item-detail">上层缓存命中时响应时间从 50ms 降至 0-10ms</span>
</div>
</div>
<div class="explanation-item">
<div class="item-icon">💰</div>
<div class="item-icon">
💰
</div>
<div class="item-text">
<strong>降低成本</strong>
<br />
<span class="item-detail"
>减少昂贵的数据库查询节省服务器资源</span
>
<br>
<span class="item-detail">减少昂贵的数据库查询节省服务器资源</span>
</div>
</div>
</div>
@@ -5,38 +5,69 @@
<template>
<div class="product-cache-demo">
<div class="header">
<div class="title">商品详情页缓存系统实战</div>
<div class="subtitle">完整的三级缓存架构 + 监控面板</div>
<div class="title">
商品详情页缓存系统实战
</div>
<div class="subtitle">
完整的三级缓存架构 + 监控面板
</div>
</div>
<div class="architecture-overview">
<div class="overview-title">系统架构</div>
<div class="overview-title">
系统架构
</div>
<div class="architecture-diagram">
<div class="layer client">
<div class="layer-label">客户端</div>
<div class="layer-icon">📱</div>
<div class="layer-label">
客户端
</div>
<div class="layer-icon">
📱
</div>
</div>
<div class="arrow"></div>
<div class="layer local-cache" :class="{ hit: currentLevel === 1 }">
<div class="layer-label">L1: 本地缓存 (Caffeine)</div>
<div class="arrow">
</div>
<div
class="layer local-cache"
:class="{ hit: currentLevel === 1 }"
>
<div class="layer-label">
L1: 本地缓存 (Caffeine)
</div>
<div class="layer-stats">
<div>容量: 1000</div>
<div>TTL: 30s</div>
<div>命中: {{ localHits }}</div>
</div>
</div>
<div class="arrow"></div>
<div class="layer redis-cache" :class="{ hit: currentLevel === 2 }">
<div class="layer-label">L2: Redis 集群</div>
<div class="arrow">
</div>
<div
class="layer redis-cache"
:class="{ hit: currentLevel === 2 }"
>
<div class="layer-label">
L2: Redis 集群
</div>
<div class="layer-stats">
<div>容量: 100</div>
<div>TTL: 5min</div>
<div>命中: {{ redisHits }}</div>
</div>
</div>
<div class="arrow"></div>
<div class="layer database" :class="{ hit: currentLevel === 3 }">
<div class="layer-label">L3: MySQL 数据库</div>
<div class="arrow">
</div>
<div
class="layer database"
:class="{ hit: currentLevel === 3 }"
>
<div class="layer-label">
L3: MySQL 数据库
</div>
<div class="layer-stats">
<div>持久化存储</div>
<div>查询: {{ dbQueries }}</div>
@@ -47,21 +78,35 @@
<div class="demo-sections">
<div class="section query-demo">
<div class="section-title">查询商品</div>
<div class="section-title">
查询商品
</div>
<div class="query-controls">
<input
v-model="productId"
type="text"
placeholder="输入商品ID (如: P001)"
class="product-input"
/>
<button class="query-btn" @click="queryProduct" :disabled="querying">
>
<button
class="query-btn"
:disabled="querying"
@click="queryProduct"
>
{{ querying ? '查询中...' : '查询' }}
</button>
<button class="reset-btn" @click="resetDemo">重置</button>
<button
class="reset-btn"
@click="resetDemo"
>
重置
</button>
</div>
<div class="query-result" v-if="queryResult">
<div
v-if="queryResult"
class="query-result"
>
<div class="result-header">
<span class="result-icon">{{ queryResult.icon }}</span>
<span class="result-title">{{ queryResult.title }}</span>
@@ -95,8 +140,13 @@
</div>
</div>
<div class="query-flow" v-if="queryFlow.length > 0">
<div class="flow-title">查询流程</div>
<div
v-if="queryFlow.length > 0"
class="query-flow"
>
<div class="flow-title">
查询流程
</div>
<div class="flow-steps">
<div
v-for="(step, index) in queryFlow"
@@ -104,50 +154,82 @@
class="flow-step"
:class="step.type"
>
<div class="step-level">{{ step.level }}</div>
<div class="step-result">{{ step.result }}</div>
<div class="step-time">{{ step.time }}ms</div>
<div class="step-level">
{{ step.level }}
</div>
<div class="step-result">
{{ step.result }}
</div>
<div class="step-time">
{{ step.time }}ms
</div>
</div>
</div>
</div>
</div>
<div class="section cache-monitor">
<div class="section-title">缓存监控</div>
<div class="section-title">
缓存监控
</div>
<div class="metrics-grid">
<div class="metric-card">
<div class="metric-label">总请求数</div>
<div class="metric-value">{{ metrics.totalRequests }}</div>
<div class="metric-label">
总请求数
</div>
<div class="metric-value">
{{ metrics.totalRequests }}
</div>
</div>
<div class="metric-card">
<div class="metric-label">本地缓存命中</div>
<div class="metric-value local">{{ localHits }}</div>
<div class="metric-label">
本地缓存命中
</div>
<div class="metric-value local">
{{ localHits }}
</div>
</div>
<div class="metric-card">
<div class="metric-label">Redis命中</div>
<div class="metric-value redis">{{ redisHits }}</div>
<div class="metric-label">
Redis命中
</div>
<div class="metric-value redis">
{{ redisHits }}
</div>
</div>
<div class="metric-card">
<div class="metric-label">数据库查询</div>
<div class="metric-value db">{{ dbQueries }}</div>
<div class="metric-label">
数据库查询
</div>
<div class="metric-value db">
{{ dbQueries }}
</div>
</div>
</div>
<div class="hit-rate-display">
<div class="rate-label">整体命中率</div>
<div class="rate-value">{{ overallHitRate }}%</div>
<div class="rate-label">
整体命中率
</div>
<div class="rate-value">
{{ overallHitRate }}%
</div>
<div class="rate-bar">
<div
class="rate-fill"
:style="{ width: overallHitRate + '%' }"
></div>
/>
</div>
<div class="rate-target">
目标: > 90%
</div>
<div class="rate-target">目标: > 90%</div>
</div>
<div class="cache-stats-detail">
<div class="stats-title">详细统计</div>
<div class="stats-title">
详细统计
</div>
<div class="stats-list">
<div class="stat-item">
<span class="stat-label">本地缓存命中率:</span>
@@ -171,35 +253,61 @@
</div>
<div class="features">
<div class="feature-title">核心特性</div>
<div class="feature-title">
核心特性
</div>
<div class="feature-grid">
<div class="feature-item">
<div class="feature-icon">🛡</div>
<div class="feature-name">多级缓存</div>
<div class="feature-icon">
🛡
</div>
<div class="feature-name">
多级缓存
</div>
<div class="feature-desc">
本地缓存 + Redis 双层防护减少 99% 数据库查询
</div>
</div>
<div class="feature-item">
<div class="feature-icon">🔒</div>
<div class="feature-name">防击穿</div>
<div class="feature-desc">互斥锁保护热点数据避免并发查询数据库</div>
<div class="feature-icon">
🔒
</div>
<div class="feature-name">
防击穿
</div>
<div class="feature-desc">
互斥锁保护热点数据避免并发查询数据库
</div>
</div>
<div class="feature-item">
<div class="feature-icon">🎯</div>
<div class="feature-name">防穿透</div>
<div class="feature-desc">缓存空对象防止查询不存在的商品</div>
<div class="feature-icon">
🎯
</div>
<div class="feature-name">
防穿透
</div>
<div class="feature-desc">
缓存空对象防止查询不存在的商品
</div>
</div>
<div class="feature-item">
<div class="feature-icon"></div>
<div class="feature-name">随机 TTL</div>
<div class="feature-desc">避免缓存雪崩过期时间加随机值</div>
<div class="feature-icon">
</div>
<div class="feature-name">
随机 TTL
</div>
<div class="feature-desc">
避免缓存雪崩过期时间加随机值
</div>
</div>
</div>
</div>
<div class="code-preview">
<div class="code-title">核心代码片段</div>
<div class="code-title">
核心代码片段
</div>
<pre class="code-block"><code>//
public Product getProduct(String productId) {
// L1: