美团路径缓存淘汰策略全解析(性能 vs 精度 vs 成本的三难选择)

📌 一、背景:为什么需要路径缓存?

在美团骑手实时导航系统中,每天超过 5 亿次路径规划请求,如果每次都重新计算:

  • ❌ 地图服务调用次数剧增(高德/自研)
  • ❌ 响应延迟上升,影响 ETA 和调度时效
  • ❌ 多个相似订单浪费计算资源

所以我们引入了路径缓存服务 PathCache,用于加速以下场景:

  • 相似起终点订单(比如同小区商户 → 楼盘外卖点)
  • 骑手换单前后的路径尝试
  • 派单调度模拟(每个骑手尝试不同路径)

📌 二、路径缓存的基本结构

✅ 缓存 Key 设计

ts 复制代码
cacheKey = `${startLat}_${startLng}_${endLat}_${endLng}_${timeSlice}`

加入时间片段(例如 15分钟粒度)避免老路况影响精度。


✅ 缓存 Value 结构(简化)

ts 复制代码
interface PathCacheEntry {
  route: RouteSegment[];       // 路线分段信息
  score: number;               // 规划打分
  trafficLevel: string;        // 当时的路况等级
  createTime: number;          // 路径生成时间戳
  usedCount: number;           // 被命中次数
  etaSnapshot: number;         // 当时 ETA 值
}

📌 三、淘汰策略设计核心:缓存不能太旧,也不能太少

我们评估过以下淘汰算法:

策略 特点 是否使用
FIFO 简单,但命中率低 否 ❌
LRU 保活常用路径,适合骑手高频路线 是 ✅
LFU 命中频率优先,但会留"老废数据" 否 ❌
TTL+LRU LRU为主,超期也淘汰 是 ✅
自定义分级 热路网保留更久,冷路快淘汰 是 ✅

📦 四、核心实现片段(Node.js 伪代码)

✅ 路径缓存读写:

js 复制代码
const cacheMap = new Map()

function getPathFromCache(key) {
  const entry = cacheMap.get(key)
  if (!entry) return null

  const now = Date.now()
  if (now - entry.createTime > 10 * 60 * 1000) { // 超过10分钟失效
    cacheMap.delete(key)
    return null
  }

  entry.usedCount += 1
  return entry
}

function savePathToCache(key, data) {
  cacheMap.set(key, {
    ...data,
    createTime: Date.now(),
    usedCount: 1
  })
}

✅ 淘汰策略:定时任务 + 限制容量

js 复制代码
const MAX_CACHE_SIZE = 100000

setInterval(() => {
  const entries = Array.from(cacheMap.entries())

  // 超时 + 命中次数低 的组合淘汰策略
  entries.sort((a, b) => {
    return a[1].usedCount - b[1].usedCount
  })

  if (entries.length > MAX_CACHE_SIZE) {
    const dropCount = entries.length - MAX_CACHE_SIZE
    for (let i = 0; i < dropCount; i++) {
      cacheMap.delete(entries[i][0])
    }
  }
}, 60000)

📈 五、缓存命中率优化方案(真实策略)

✅ 1. 起终点"相似化"

通过对经纬度 hash 到格子区域:

ts 复制代码
function simplifyCoord(lat, lng) {
  return `${Math.round(lat * 1000)},${Math.round(lng * 1000)}`
}

命中率提升约 23.1%


✅ 2. 多路缓存(小批量候选)

为了防止主缓存被挤爆,我们引入 冷热分级策略

text 复制代码
一级缓存:热门路径(热门商圈配送) → Redis
二级缓存:普通路径 → LRU 本地缓存
三级备份:异步写入本地 LevelDB

✅ 3. 同区域同向缓存迁移

举例:

A小区 → 商场B 的路径,可应用到 A小区 → 商场B 门口快递点,只需增补尾段

这种近似路径继承策略 ,帮助我们降低路径规划调用约 14.7%


📊 六、实战效果对比

指标 未优化 使用 PathCache(全策略)
平均路径耗时 123ms 23ms
地图服务 QPS 降低 - 减少 67% 请求
缓存命中率 18% 64.5%
错误路径命中率 - < 0.9%(有 ETA 反查兜底)

📌 七、工程挑战总结

挑战 解决策略
异常旧路径未失效 TTL+并发清理
路况快速波动 加入时间片 hash
高峰缓存击穿 Redis 热点缓存 + fallback 兜底
多版本路径重复命中 增加 algo_version 区分 key

✅ 总结

路径缓存系统是一个低成本、高收益的优化方案,但做好它不简单:

  1. 要理解"骑手路径行为"和"地理分布模式"
  2. 要能高效设计缓存 key、淘汰策略、实时清理
  3. 要和 ETA 模型打通,确保预测数据不过时
  4. 要可观测、可复盘、可 Debug(日志审计 + 兜底机制)
相关推荐
xingsfdz27 分钟前
Java微服务-新建demo
微服务·云原生·架构
白露与泡影30 分钟前
阿里一面:微服务拆分需要考虑什么因素?
微服务·云原生·架构
大咖分享课33 分钟前
微服务数据一致性技术解析:从单体到微服务的数据困局
微服务·云原生·架构·最佳实践·微服务数据一致性
烛阴1 小时前
Python多进程开发实战:轻松突破GIL瓶颈
前端·python
爱分享的程序员1 小时前
前端面试专栏-主流框架:11. React Router路由原理与实践
前端·javascript·react.js·面试
weixin_459074351 小时前
在el-image组件的预览中添加打印功能(自定义功能)
前端·javascript·vue.js
追逐时光者1 小时前
一个基于 .NET 8 开源免费、高性能、低占用的博客系统
后端·.net
知否技术1 小时前
2025微信小程序开发实战教程(三)
前端·微信小程序
方圆想当图灵1 小时前
深入理解软件设计:领域驱动设计实战
后端·领域驱动设计
海的诗篇_2 小时前
前端开发面试题总结-vue3框架篇(二)
前端·javascript·vue.js·面试·前端框架·vue