网站开发的前端到底是什么,微信视频制作小程序,个人建设网站程序,有哪些网站可以推广架构设计之存储高性能——缓存
1. 存储系统的性能瓶颈
1.1 真实场景的性能困境
虽然我们可以通过各种手段来提升存储系统的性能#xff0c;但在某些复杂的业务场景下#xff0c;单纯依靠存储系统的性能提升可能远远不够。
典型案例#xff1a;以微博热搜系统为例 2023年…架构设计之存储高性能——缓存
1. 存储系统的性能瓶颈
1.1 真实场景的性能困境
虽然我们可以通过各种手段来提升存储系统的性能但在某些复杂的业务场景下单纯依靠存储系统的性能提升可能远远不够。
典型案例以微博热搜系统为例 2023年春节某明星离婚事件爆发的15分钟内
阅读量从50万飙升至1.2亿评论请求达到每秒87万次服务器响应延迟超过5秒
此时单纯升级数据库收效甚微总的来说数据库的执行流程如下 #mermaid-svg-XRxfQvGBFETjo8WQ {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-XRxfQvGBFETjo8WQ .error-icon{fill:#552222;}#mermaid-svg-XRxfQvGBFETjo8WQ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-XRxfQvGBFETjo8WQ .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-XRxfQvGBFETjo8WQ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-XRxfQvGBFETjo8WQ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-XRxfQvGBFETjo8WQ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-XRxfQvGBFETjo8WQ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-XRxfQvGBFETjo8WQ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-XRxfQvGBFETjo8WQ .marker.cross{stroke:#333333;}#mermaid-svg-XRxfQvGBFETjo8WQ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-XRxfQvGBFETjo8WQ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-XRxfQvGBFETjo8WQ .cluster-label text{fill:#333;}#mermaid-svg-XRxfQvGBFETjo8WQ .cluster-label span{color:#333;}#mermaid-svg-XRxfQvGBFETjo8WQ .label text,#mermaid-svg-XRxfQvGBFETjo8WQ span{fill:#333;color:#333;}#mermaid-svg-XRxfQvGBFETjo8WQ .node rect,#mermaid-svg-XRxfQvGBFETjo8WQ .node circle,#mermaid-svg-XRxfQvGBFETjo8WQ .node ellipse,#mermaid-svg-XRxfQvGBFETjo8WQ .node polygon,#mermaid-svg-XRxfQvGBFETjo8WQ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-XRxfQvGBFETjo8WQ .node .label{text-align:center;}#mermaid-svg-XRxfQvGBFETjo8WQ .node.clickable{cursor:pointer;}#mermaid-svg-XRxfQvGBFETjo8WQ .arrowheadPath{fill:#333333;}#mermaid-svg-XRxfQvGBFETjo8WQ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-XRxfQvGBFETjo8WQ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-XRxfQvGBFETjo8WQ .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-XRxfQvGBFETjo8WQ .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-XRxfQvGBFETjo8WQ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-XRxfQvGBFETjo8WQ .cluster text{fill:#333;}#mermaid-svg-XRxfQvGBFETjo8WQ .cluster span{color:#333;}#mermaid-svg-XRxfQvGBFETjo8WQ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-XRxfQvGBFETjo8WQ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 1. SQL解析 2. 索引查询 3. 结果返回 用户请求 数据库 CPU 磁盘 网络 由此我们可以发现数据库存在的三重性能枷锁
磁盘IO瓶颈机械磁盘查询时间过长CPU计算瓶颈复杂的SQL解析与聚合计算网络带宽瓶颈重复数据传输占用带宽
1.2 缓存的价值发现
缓存就是为了弥补存储系统在这些复杂业务场景下的不足缓存的基本原理就是将可能重复使用的数据放到内存中一次生成多次使用避免每次使用都去访问存储系统缓存适用的典型场景有如下两类。
读多写少的场景
场景读写比例传统数据库QPS引入缓存后QPS微信朋友圈100:13,000450,000小红书推荐流50:15,000300,000电商商品页200:12,500350,000
需要复杂计算结果的场景
# 用户画像推荐计算无缓存
def generate_recommend(user_id):# 1. 读取用户行为数据50ms # 2. 获取商品特征数据100ms# 3. 矩阵计算200ms# 总耗时350ms# 引入计算结果缓存后
if cache.exists(user_id):return cache.get(user_id) # 0.5ms读取缓存
else:result complex_calculation() # 计算耗时350mscache.set(user_id, result) # 缓存结果return result缓存核心价值
高速响应内存访问速度比SSD快1000倍成本优化1GB内存成本大概是同等IOPS的SSD成本的1/30卸流70%-90%的请求不会穿透到数据库
缓存虽然存在这么多优点但同时也给架构设计引入了更多复杂性。如果没有针对缓存的复杂性进行处理某些场景下甚至会导致整个系统崩溃。接下来我们来盘点一下使用缓存可能存在的那些问题。
2. 缓存穿透无形的攻击
2.1 问题现象与危害
缓存穿透是指当请求的数据在缓存系统和数据库中均不存在时大量无效查询直接冲击数据库的现象可能导致数据库过载甚至崩溃。例如恶意攻击者构造大量不存在的ID进行查询如ID为999999或业务代码逻辑错误导致频繁查询无效数据。
攻击特征
恶意请求不存在的数据如负整数ID数据库持续空查询缓存命中率为0%
连锁反应 #mermaid-svg-ANhXFC55Fo61pUGu {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-ANhXFC55Fo61pUGu .error-icon{fill:#552222;}#mermaid-svg-ANhXFC55Fo61pUGu .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ANhXFC55Fo61pUGu .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-ANhXFC55Fo61pUGu .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ANhXFC55Fo61pUGu .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ANhXFC55Fo61pUGu .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ANhXFC55Fo61pUGu .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ANhXFC55Fo61pUGu .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ANhXFC55Fo61pUGu .marker.cross{stroke:#333333;}#mermaid-svg-ANhXFC55Fo61pUGu svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ANhXFC55Fo61pUGu .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-ANhXFC55Fo61pUGu text.actortspan{fill:black;stroke:none;}#mermaid-svg-ANhXFC55Fo61pUGu .actor-line{stroke:grey;}#mermaid-svg-ANhXFC55Fo61pUGu .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-ANhXFC55Fo61pUGu .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-ANhXFC55Fo61pUGu #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-ANhXFC55Fo61pUGu .sequenceNumber{fill:white;}#mermaid-svg-ANhXFC55Fo61pUGu #sequencenumber{fill:#333;}#mermaid-svg-ANhXFC55Fo61pUGu #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-ANhXFC55Fo61pUGu .messageText{fill:#333;stroke:#333;}#mermaid-svg-ANhXFC55Fo61pUGu .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-ANhXFC55Fo61pUGu .labelText,#mermaid-svg-ANhXFC55Fo61pUGu .labelTexttspan{fill:black;stroke:none;}#mermaid-svg-ANhXFC55Fo61pUGu .loopText,#mermaid-svg-ANhXFC55Fo61pUGu .loopTexttspan{fill:black;stroke:none;}#mermaid-svg-ANhXFC55Fo61pUGu .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-ANhXFC55Fo61pUGu .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-ANhXFC55Fo61pUGu .noteText,#mermaid-svg-ANhXFC55Fo61pUGu .noteTexttspan{fill:black;stroke:none;}#mermaid-svg-ANhXFC55Fo61pUGu .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-ANhXFC55Fo61pUGu .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-ANhXFC55Fo61pUGu .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-ANhXFC55Fo61pUGu .actorPopupMenu{position:absolute;}#mermaid-svg-ANhXFC55Fo61pUGu .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-ANhXFC55Fo61pUGu .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-ANhXFC55Fo61pUGu .actor-man circle,#mermaid-svg-ANhXFC55Fo61pUGu line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-ANhXFC55Fo61pUGu :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Hacker Cache DB Monitor OpsTeam App User 请求不存在的key 返回null 查询不存在key 返回空结果 请求不存在的key 返回null 查询不存在key 返回空结果 loop [每秒10万次请求...] CPU使用率100% 触发告警 尝试扩容/限流 扩容失败 服务不可用503 Hacker Cache DB Monitor OpsTeam App User 2.2 综合防御方案
方案一布隆过滤器
通过布隆过滤器预先存储所有合法数据的哈希值请求到达时快速判断数据是否存在若不存在则直接拦截
// 初始化布隆过滤器
BloomFilterString bloomFilter BloomFilter.create(Funnels.stringFunnel(), 1000000, // 预期元素量0.01 // 误判率
);// 加载有效key
for(String key: validKeys) {bloomFilter.put(key);
}// 请求处理流程
if(!bloomFilter.mightContain(key)) {return null; // 直接拦截无效请求
} 方案二空值缓存策略
对于查询结果为空的请求在缓存中存储空值并设置较短过期时间如30秒减少重复穿透数据库的风险。
def get_data(key):data cache.get(key)if data is None: # 特殊标识符缓存空值if cache.get(fempty_{key}) is not None: return None# 查询数据库db_data db.query(key) if db_data:cache.set(key, db_data, timeout300)else:# 缓存空值5分钟cache.set(fempty_{key}, NONE, timeout300) return db_data方案三热点Key预热
热点key预热是指在系统启动前提前将相关的热点数据加载到缓存中避免在用户请求时先查询数据库再将数据缓存的问题。这样可以确保用户在查询时直接从预热的缓存中获取数据提高系统的响应速度和用户体验。
-- 实时分析DB查询日志
SELECT query_key, COUNT(*) as freq
FROM access_log
WHERE resultempty
GROUP BY query_key
HAVING freq 1000 -- 阈值控制防御效果对比
方案拦截率误杀率成本布隆过滤器99.9%1%低空值缓存100%0%中熔断机制100%50%高
3. 缓存雪崩导致系统崩溃的多米诺骨牌
3.1 灾难发生原理
缓存雪崩是指在同一时间段内大量缓存数据集中失效或缓存服务故障由于缓存失效后业务系统会重新生成缓存因此需要再次访问数据库导致数据库因瞬时高并发请求而压力激增甚至崩溃的系统性风险。该现象通常由缓存集中过期、服务宕机或流量激增引发需通过分散失效时间、多级缓存架构等策略应对。
典型雪崩场景
某电商00:00大促开始10万用户同时触发缓存到期数据库瞬时收到百万级请求MySQL连接池耗尽
雪崩过程分析 #mermaid-svg-Jte837YqTbd4x7nB {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-Jte837YqTbd4x7nB .error-icon{fill:#552222;}#mermaid-svg-Jte837YqTbd4x7nB .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Jte837YqTbd4x7nB .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-Jte837YqTbd4x7nB .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Jte837YqTbd4x7nB .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Jte837YqTbd4x7nB .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Jte837YqTbd4x7nB .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Jte837YqTbd4x7nB .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Jte837YqTbd4x7nB .marker.cross{stroke:#333333;}#mermaid-svg-Jte837YqTbd4x7nB svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Jte837YqTbd4x7nB .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-Jte837YqTbd4x7nB text.actortspan{fill:black;stroke:none;}#mermaid-svg-Jte837YqTbd4x7nB .actor-line{stroke:grey;}#mermaid-svg-Jte837YqTbd4x7nB .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-Jte837YqTbd4x7nB .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-Jte837YqTbd4x7nB #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-Jte837YqTbd4x7nB .sequenceNumber{fill:white;}#mermaid-svg-Jte837YqTbd4x7nB #sequencenumber{fill:#333;}#mermaid-svg-Jte837YqTbd4x7nB #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-Jte837YqTbd4x7nB .messageText{fill:#333;stroke:#333;}#mermaid-svg-Jte837YqTbd4x7nB .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-Jte837YqTbd4x7nB .labelText,#mermaid-svg-Jte837YqTbd4x7nB .labelTexttspan{fill:black;stroke:none;}#mermaid-svg-Jte837YqTbd4x7nB .loopText,#mermaid-svg-Jte837YqTbd4x7nB .loopTexttspan{fill:black;stroke:none;}#mermaid-svg-Jte837YqTbd4x7nB .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-Jte837YqTbd4x7nB .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-Jte837YqTbd4x7nB .noteText,#mermaid-svg-Jte837YqTbd4x7nB .noteTexttspan{fill:black;stroke:none;}#mermaid-svg-Jte837YqTbd4x7nB .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-Jte837YqTbd4x7nB .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-Jte837YqTbd4x7nB .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-Jte837YqTbd4x7nB .actorPopupMenu{position:absolute;}#mermaid-svg-Jte837YqTbd4x7nB .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-Jte837YqTbd4x7nB .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-Jte837YqTbd4x7nB .actor-man circle,#mermaid-svg-Jte837YqTbd4x7nB line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-Jte837YqTbd4x7nB :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 缓存 DB连接池 应用服务器 用户 所有参与者 T0: 缓存批量失效 请求数据 数据失效转发请求到DB T0.5s: DB连接池满100% 请求数据库连接 无可用连接 T1s: 响应延迟超时5000ms 请求处理 处理中等待DB连接 响应延迟超时 T3s: 应用服务器线程池耗尽 更多请求 请求被拒绝线程池耗尽 T10s: 服务全面崩溃 请求服务 服务不可用 缓存 DB连接池 应用服务器 用户 所有参与者 3.2 解决方案
策略一过期时间离散化
// 基础缓存时间1小时
long baseExpire 3600; // 添加随机抖动±10分钟
long randomOffset (long)(Math.random() * 1200 - 600);// 最终过期时间
long finalExpire baseExpire randomOffset;策略二双层缓存架构 #mermaid-svg-qrC9pNdMyO3TzP5X {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-qrC9pNdMyO3TzP5X .error-icon{fill:#552222;}#mermaid-svg-qrC9pNdMyO3TzP5X .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-qrC9pNdMyO3TzP5X .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-qrC9pNdMyO3TzP5X .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-qrC9pNdMyO3TzP5X .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-qrC9pNdMyO3TzP5X .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-qrC9pNdMyO3TzP5X .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-qrC9pNdMyO3TzP5X .marker{fill:#333333;stroke:#333333;}#mermaid-svg-qrC9pNdMyO3TzP5X .marker.cross{stroke:#333333;}#mermaid-svg-qrC9pNdMyO3TzP5X svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-qrC9pNdMyO3TzP5X .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-qrC9pNdMyO3TzP5X .cluster-label text{fill:#333;}#mermaid-svg-qrC9pNdMyO3TzP5X .cluster-label span{color:#333;}#mermaid-svg-qrC9pNdMyO3TzP5X .label text,#mermaid-svg-qrC9pNdMyO3TzP5X span{fill:#333;color:#333;}#mermaid-svg-qrC9pNdMyO3TzP5X .node rect,#mermaid-svg-qrC9pNdMyO3TzP5X .node circle,#mermaid-svg-qrC9pNdMyO3TzP5X .node ellipse,#mermaid-svg-qrC9pNdMyO3TzP5X .node polygon,#mermaid-svg-qrC9pNdMyO3TzP5X .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-qrC9pNdMyO3TzP5X .node .label{text-align:center;}#mermaid-svg-qrC9pNdMyO3TzP5X .node.clickable{cursor:pointer;}#mermaid-svg-qrC9pNdMyO3TzP5X .arrowheadPath{fill:#333333;}#mermaid-svg-qrC9pNdMyO3TzP5X .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-qrC9pNdMyO3TzP5X .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-qrC9pNdMyO3TzP5X .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-qrC9pNdMyO3TzP5X .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-qrC9pNdMyO3TzP5X .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-qrC9pNdMyO3TzP5X .cluster text{fill:#333;}#mermaid-svg-qrC9pNdMyO3TzP5X .cluster span{color:#333;}#mermaid-svg-qrC9pNdMyO3TzP5X div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-qrC9pNdMyO3TzP5X :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 存在 不存在 存在 不存在 客户端请求 Local Cache 返回数据 Redis集群 返回更新本地缓存 数据库查询 数据回填缓存 策略三缓存永续化异步更新
热点数据永不过期针对高频访问数据采用后台更新策略。
def get_data(key):data cache.get(key)if not data:# 返回旧数据保证可用性stale_data cache.get(fstale_{key}) if stale_data:return stale_data# 异步更新async_update_queue.push(key) return Nonereturn data# 后台更新任务
def update_cache(key):db_data db.query(key)cache.set(key, db_data, timeout3600)cache.set(fstale_{key}, db_data) # 永不超时副本4. 缓存热点流量的海啸
虽然缓存系统性能大大提升不过对于一些热度特别高的数据如果所有的请求都命中同一份缓存数据则这份数据所在的缓存服务器压力也十分之大。例如某知名明星微博宣布恋爱短时间内上千万的用户都会来围观。缓存热点的解决方案就是复制多份缓存将请求分散到多个缓存服务器上减轻缓存热点导致的单台缓存服务器压力。以新浪微博为例对于粉丝数超过100万的明星每条微博都可以生成100份缓存缓存的数据是一样的通过在缓存的key里面加上编号进行区分每次读缓存时都随机读取其中某份缓存。
5. 缓存技术盘点
5.1 主流缓存技术对比
缓存系统读写性能数据特性典型应用场景Redis读10万/写8万丰富数据结构会话/计数器/队列Memcached读15万/写12万简单键值对象缓存Ehcache读50万/写30万JVM堆内存储JAVA应用本地缓存Caffeine读120万/写80万高并发优化高性能本地缓存CDN百万级QPS静态资源图片/视频分发
5.2 多级缓存架构设计 #mermaid-svg-oU54Cz6ys2J71tbG {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-oU54Cz6ys2J71tbG .error-icon{fill:#552222;}#mermaid-svg-oU54Cz6ys2J71tbG .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-oU54Cz6ys2J71tbG .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-oU54Cz6ys2J71tbG .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-oU54Cz6ys2J71tbG .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-oU54Cz6ys2J71tbG .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-oU54Cz6ys2J71tbG .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-oU54Cz6ys2J71tbG .marker{fill:#333333;stroke:#333333;}#mermaid-svg-oU54Cz6ys2J71tbG .marker.cross{stroke:#333333;}#mermaid-svg-oU54Cz6ys2J71tbG svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-oU54Cz6ys2J71tbG .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-oU54Cz6ys2J71tbG .cluster-label text{fill:#333;}#mermaid-svg-oU54Cz6ys2J71tbG .cluster-label span{color:#333;}#mermaid-svg-oU54Cz6ys2J71tbG .label text,#mermaid-svg-oU54Cz6ys2J71tbG span{fill:#333;color:#333;}#mermaid-svg-oU54Cz6ys2J71tbG .node rect,#mermaid-svg-oU54Cz6ys2J71tbG .node circle,#mermaid-svg-oU54Cz6ys2J71tbG .node ellipse,#mermaid-svg-oU54Cz6ys2J71tbG .node polygon,#mermaid-svg-oU54Cz6ys2J71tbG .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-oU54Cz6ys2J71tbG .node .label{text-align:center;}#mermaid-svg-oU54Cz6ys2J71tbG .node.clickable{cursor:pointer;}#mermaid-svg-oU54Cz6ys2J71tbG .arrowheadPath{fill:#333333;}#mermaid-svg-oU54Cz6ys2J71tbG .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-oU54Cz6ys2J71tbG .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-oU54Cz6ys2J71tbG .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-oU54Cz6ys2J71tbG .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-oU54Cz6ys2J71tbG .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-oU54Cz6ys2J71tbG .cluster text{fill:#333;}#mermaid-svg-oU54Cz6ys2J71tbG .cluster span{color:#333;}#mermaid-svg-oU54Cz6ys2J71tbG div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-oU54Cz6ys2J71tbG :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 未命中 未命中 未命中 未命中 未命中 客户端 浏览器缓存 CDN边缘节点 API网关缓存 本地应用缓存 Redis集群 数据库 回填Redis 回填本地缓存 数据返回客户端 5.3 缓存治理关键指标
命中率看板
核心业务缓存命中率≥95%波动阈值±5%告警
穿透防护看板
布隆过滤器拦截率空值Key比例
热点监控
# Redis热点Key检测命令
redis-cli --hotkeys
# 输出示例
[27%] Hot key product_123 found
[15%] Hot key user_profile_456 found结语
作为架构师想熟练将缓存融合到架构中需要掌握三点
设计缓存策略过期策略/更新策略平衡系统哲学空间换时间/延迟换吞吐掌握技术特性Redis vs Memcached
缓存设计的黄金法则
任何缓存都应有失效策略任何热key都要有疏散方案任何缓存系统必须可降级任何数据最终以持久层为准 “优秀的架构师不会将缓存视为独立组件而是将其作为数据流动的调节阀——在风暴来临前蓄水防洪在干旱季节开闸放水方能在数据洪流中构建生生不息的技术生态。” —— 《架构之道·缓存卷》 关注 是对原创的最大认可你的每一个关注 都是技术生态圈的1节点 开启通知下一篇《架构设计之计算高性能——单体服务器高性能》内容更新时你就是技术圈最前沿的「极客」