简介:本资源是一份面向互联网中后台架构师、O2O业务系统设计者及CRM领域技术从业者的深度实践文档,聚焦美团O2O场景下B端客户关系管理系统的整体架构设计与落地逻辑。文档系统阐述了CRM如何支撑销售线索获取与转化(公私海模型、45天期限机制、BD自助延期)、运营提效(中台化工作台、合同与品类管理下沉)、数据驱动决策(竞争情报链路、总部-城市任务下发)及移动办公场景(MOMA客户端定位推荐、拜访数据聚合)四大核心能力。资源为单个Word文档(.doc),大小仅20KB,内容精炼但信息密度高,涵盖技术架构分层(MDC/PMC/Deal中心等底层依赖)、业务模型抽象与演进思考,适合快速掌握头部平台CRM系统的设计哲学与工程权衡。目前已有229人学习下载,是理解O2O线下能力数字化底座的典型参考案例。
1. 美团CRM不是销售台账,而是O2O线下能力的实时调度中枢
很多人第一次看到“美团CRM系统架构设计”这个标题,下意识会把它归类为传统企业里那种录入客户电话、打标签、发邮件的SaaS工具。但实际拆开这份文档你会发现:它根本不是在管“人”,而是在调度“门店”——一个POI(Point of Interest)从被爬虫发现、BD扫街认领、签约上单、价格干预、合同续期,到最终因经营异常被下线,整个生命周期全部由CRM驱动。它的核心指标不是成交率或回款周期,而是“城市端对竞对价格劣势的平均响应时长”“私海线索45天内签约转化率”“运营中台单人覆盖门店数”。这种设计源于O2O的本质矛盾:平台不生产服务,只协调供给;而供给方(商户)高度离散、动态变化、强地域性。因此CRM必须能实时感知物理世界的变动——比如某商圈新开3家火锅店,系统要自动触发BD拜访任务;某酒店间夜量连续两周下滑,要联动供给链系统冻结其特价套餐。它不是后台数据库,而是连接总部策略引擎与地面执行单元的神经突触。适合正在搭建本地生活服务平台、面临BD人力瓶颈、或需要将地推团队转向精细化运营的技术负责人与架构师。
2. 公私海模型:用状态机+时间阈值实现线下资源的动态博弈
CRM对销售阶段的支持,本质是解决“如何让有限BD高效争夺无限POI”的问题。美团没有采用静态分配或抢单机制,而是构建了一套带时效约束的状态机模型,其设计逻辑直指O2O业务的物理特性:商户位置固定但商机转瞬即逝,BD行程不可预测但需结果可量化。
2.1 公私海状态流转的底层规则
公私海并非简单划分数据权限,而是定义了POI在销售漏斗中的可操作性状态。每个POI在CRM中拥有三个关键时间戳字段:
private_start_time:BD认领时刻last_visit_time:最近一次有效拜访时间(需提交含照片的拜访记录)last_sign_time:最近一次签约/续约时间
系统通过定时任务(每15分钟扫描)驱动状态变更,核心判定逻辑如下:
-- 每15分钟执行的巡检SQL(伪代码) UPDATE poi SET status = 'public', reason = 'timeout_no_visit' WHERE status = 'private' AND last_visit_time < NOW() - INTERVAL 15 DAY AND last_sign_time IS NULL; UPDATE poi SET status = 'public', reason = 'timeout_no_sign' WHERE status = 'private' AND last_sign_time < NOW() - INTERVAL 30 DAY AND last_visit_time IS NOT NULL;注意:这里的15天未拜访与30天未签约并非硬编码,而是通过配置中心动态下发。不同城市可设置差异化阈值——例如北上广深BD密度高,设为7天/14天;三四线城市则延长至20天/45天,避免因交通成本导致资源沉没。
2.2 私海保护期的弹性控制机制
文档提到“特殊情况下可通过自助延期或上级分配延长私海有效期”,这背后是一套轻量级审批流设计。当BD在MOMA客户端点击“申请延期”时,系统触发以下动作:
- 校验当前POI是否满足延期条件(如已提交≥3次有效拜访记录、有明确谈判障碍说明)
- 自动生成审批单,推送至该BD直属主管的企业微信
- 主管在5分钟内点击“同意”后,系统执行:
参数说明:# 调用核心服务API重置时间戳 curl -X POST "https://crm-core.meituan.com/v1/poi/extend-private" \ -H "Authorization: Bearer ${token}" \ -d '{"poi_id":"123456","extend_days":30,"reason":"商户要求独家合作条款谈判"}'extend_days为新增保护期天数(非总时长),reason字段强制要求填写且长度≥10字符,防止滥用。
提示:所有延期操作均写入审计日志并同步至风控系统。若同一BD月度延期超5次,其私海认领配额自动下调20%,形成闭环治理。
2.3 公海资源池的智能分发策略
公海不是随机池,而是按地理热力+商业价值双维度排序。系统每日凌晨2点执行聚合计算:
| 维度 | 计算方式 | 权重 |
|---|---|---|
| 地理热度 | 基于LBS数据统计半径500米内未覆盖POI数量 | 40% |
| 商业价值 | MDC提供的POI历史GMV分位数 + 竞对在线状态(是否在饿了么/大众点评上线) | 60% |
分发时采用“轮询+能力匹配”混合算法:
- 新入职BD优先获得低价值高密度区域(练手)
- 高绩效BD自动获得高价值单点POI(如三甲医院周边药店)
- 所有分发结果通过消息队列(Kafka)推送到MOMA客户端,BD端展示时已预加载周边3公里POI详情页
这种设计使资源分配从“人找店”变为“店找人”,将BD的移动轨迹转化为可优化的路径规划问题。
3. Deal中心:从单体模块到领域服务的微服务化实践
在CRM系统演进中,“Deal中心”的拆分是微服务化的典型范例。它解决的不是技术炫技,而是业务复杂性爆炸带来的协作熵增——当团购、外卖、酒店等业务线都需调用“Deal”对象时,原单体应用中一个字段变更需全链路回归测试,发布周期长达2周。
3.1 Deal对象的跨域数据融合挑战
一个Deal在美团生态中天然横跨多个系统:
- 供给链系统:存储Deal基础属性(名称、价格、库存)
- 主站系统:维护Deal状态机(上架/下架/售罄)
- 财务系统:记录Deal结算周期与分账规则
- MDC大数据平台:沉淀Deal历史销量、用户复购率、时段转化率
若每个业务方自行拼接这些数据,将产生大量重复ETL作业和口径不一致问题。Deal中心的核心价值在于统一数据契约:
// Deal中心对外暴露的标准Schema(精简版) { "deal_id": "string", "poi_id": "string", "title": "string", "price": { "original": "decimal", "current": "decimal", "discount_rate": "float" }, "status": "enum[online, offline, sold_out]", "sales_metrics": { "total_sold": "int", "week_growth_rate": "float", "user_repeat_rate": "float" }, "supply_chain": { "inventory": "int", "settlement_cycle": "string" } }关键设计:
sales_metrics字段不直接存储原始数据,而是通过异步任务从MDC拉取T+1聚合结果;supply_chain部分采用CQRS模式,写操作走供给链系统API,读操作由Deal中心缓存兜底,避免强依赖。
3.2 多源索引的协同检索架构
Deal中心需支撑毫秒级查询(如BD在MOMA搜索“朝阳区火锅”),但不同数据源的检索能力差异巨大:
- 供给链DB:支持精确匹配(deal_id、poi_id)
- SolrCloud:擅长全文检索(标题、描述)
- Medis(美团Redis):缓存热点Deal详情(TOP 10万)
系统采用分层路由策略:
- 先查Medis,命中则直接返回(95%请求在此层终结)
- 未命中则并发请求SolrCloud(关键词)与供给链DB(ID/POI过滤)
- 合并结果去重后,按
sales_metrics.week_growth_rate降序返回
# Python伪代码:多源并发查询协调器 def search_deals(keyword, poi_id=None): cache_result = redis.get(f"deal:{keyword}") if cache_result: return json.loads(cache_result) # 并发调用 solr_future = executor.submit(solr_search, keyword) db_future = executor.submit(db_search, poi_id) if poi_id else None solr_results = solr_future.result() db_results = db_future.result() if db_future else [] # 去重合并(以deal_id为key) merged = {r['deal_id']: r for r in solr_results + db_results} sorted_results = sorted(merged.values(), key=lambda x: x.get('sales_metrics', {}).get('week_growth_rate', 0), reverse=True) redis.setex(f"deal:{keyword}", 300, json.dumps(sorted_results)) # 缓存5分钟 return sorted_results参数说明:300为缓存过期时间(秒),week_growth_rate作为排序权重,确保高增长Deal优先曝光——这直接服务于BD的“扫街”决策:先谈增长快的店,再覆盖存量。
3.3 状态变更的事件驱动通知
Deal状态变更(如价格调整、库存清零)需实时通知下游系统,但传统RPC调用存在耦合风险。Deal中心采用事件溯源+消息广播模式:
- 所有状态变更写入MySQL binlog
- Debezium监听binlog生成CDC事件
- Kafka Topic
deal-status-change分发事件 - 订阅方(CRM工作台、价格监控系统、短信网关)各自消费处理
事件结构示例:
{ "event_id": "uuid", "deal_id": "D20230801001", "old_status": "online", "new_status": "sold_out", "trigger_source": "supply_chain_system", "timestamp": "2023-08-01T14:22:33Z" }提示:CRM工作台消费此事件后,自动将对应POI的“待办任务”状态更新为“库存告警”,并推送MOMA消息:“您负责的【XX火锅】今日库存售罄,请及时联系商户补货”。这种解耦使价格干预策略可独立迭代,无需CRM系统发版。
4. 平台化三层架构:租户隔离下的业务快速接入
当美团从团购扩展至酒店、外卖、猫眼等垂直业务时,CRM若仍按业务线重复建设,将陷入“每个新业务都要重写线索模型、公私海规则、移动端适配”的泥潭。平台化方案通过核心服务层抽象+业务应用层组装+租户层隔离,将接入周期从月级压缩至周级。
4.1 核心服务层的动态领域建模
传统CRM的“线索”概念被泛化为可配置的领域实体。核心服务层提供两套元数据管理API:
| API | 功能 | 示例调用 |
|---|---|---|
/entity/define | 定义新实体类型 | POST {"name":"Hotel","fields":[{"name":"room_count","type":"int"},{"name":"avg_night_price","type":"decimal"}]} |
/relation/define | 定义实体间关系 | POST {"from":"Hotel","to":"Brand","type":"belongs_to"} |
注册后,系统自动生成:
- MySQL分库分表(按租户ID哈希)
- SolrCloud Schema(动态添加field)
- Medis缓存Key模板(
hotel:{tenant_id}:{id})
# 创建酒店业务租户后,自动初始化其POI数据表 CREATE TABLE `poi_hotel_123` ( `id` BIGINT PRIMARY KEY, `name` VARCHAR(255), `room_count` INT, `avg_night_price` DECIMAL(10,2), `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;注意:
poi_hotel_123表名中的123为租户ID,物理隔离避免跨业务数据污染。字段room_count和avg_night_price仅对该租户生效,团购租户的POI表仍保持原有字段。
4.2 业务应用层的组件化界面组装
各业务方无需开发完整前端,而是从组件库中拖拽组合。CRM提供标准组件集:
| 组件类型 | 可配置参数 | 业务示例 |
|---|---|---|
| 线索列表 | 排序字段、筛选条件、操作按钮 | 外卖业务:按“日均单量”排序,筛选“配送半径<3km” |
| 拜访记录 | 字段模板、必填项、附件类型 | 酒店业务:必填“间夜量证明照片”,附件支持PDF合同扫描件 |
| 任务看板 | 任务来源、优先级规则、超时提醒 | 猫眼业务:来自“影院排片系统”的紧急任务,超2小时未处理自动升级 |
配置通过JSON Schema声明:
{ "component": "visit-record", "tenant_id": "hotel_tenant_001", "required_fields": ["room_count_photo", "contract_pdf"], "custom_fields": [ {"name": "check_in_rate", "type": "float", "label": "入住率"}, {"name": "ota_competitors", "type": "array", "label": "竞对平台"} ] }部署时,前端框架根据Schema动态渲染表单,后端校验器自动注入字段验证逻辑。
4.3 租户层的多通道接入协议
租户可通过三种方式接入CRM服务,适配不同技术栈:
| 接入方式 | 协议 | 典型场景 | 关键配置项 |
|---|---|---|---|
| Web集成 | iframe嵌入 | 酒店业务后台管理系统 | tenant_id,auth_token,allowed_domains |
| MOMA SDK | Android/iOS SDK | 外卖BD移动办公 | app_key,push_channel_id,location_precision |
| OpenAPI | RESTful API | 猫眼数据中台对接 | api_version,rate_limit,webhook_url |
以OpenAPI为例,租户注册时需配置Webhook地址,当Deal状态变更时,CRM核心服务层自动推送:
POST https://cat-eye-webhook.example.com/deal-update Content-Type: application/json { "tenant_id": "cat_eye_001", "event": "deal_price_changed", "data": { "deal_id": "D20230801002", "old_price": 198.00, "new_price": 168.00, "changed_by": "pricing_engine_v2" } }提示:所有租户流量通过API网关统一路由,网关按
tenant_id做限流(如猫眼租户QPS上限500)、熔断(错误率>5%自动降级)、审计(记录所有请求IP与响应耗时)。这使得业务方能专注自身逻辑,无需操心稳定性。
5. 移动端MOMA的现场决策增强:基于LBS的上下文感知引擎
MOMA(Mobile Meituan APP)不是CRM的简单移植,而是专为BD“扫街”场景重构的决策终端。其核心能力在于将GPS坐标、POI属性、历史数据、竞对情报实时融合,生成可执行建议——这要求移动端具备轻量级本地计算与云端协同能力。
5.1 LBS推荐的三级缓存策略
当BD打开MOMA并开启定位,系统需在2秒内呈现周边POI列表。为规避网络延迟,采用三级缓存:
| 层级 | 存储介质 | 更新策略 | 命中率 |
|---|---|---|---|
| L1:设备内存 | SQLite | BD启动时预加载3km内POI(含基础字段) | ~70% |
| L2:本地文件 | JSON文件 | 每日凌晨下载增量包(新增/变更POI) | ~25% |
| L3:云端API | HTTP接口 | 实时查询详情(销量、竞对状态) | ~5% |
// Android端缓存读取逻辑(Kotlin) fun loadNearbyPois(lat: Double, lng: Double): List<Poi> { // 1. 内存缓存(最快) val memoryResult = memoryCache.get("$lat,$lng") if (memoryResult != null) return memoryResult // 2. 文件缓存(次快) val fileResult = FileUtils.readJson("poi_${geohash(lat, lng, 5)}.json") if (fileResult.isNotEmpty()) { memoryCache.put("$lat,$lng", fileResult) // 回填内存 return fileResult } // 3. 网络请求(兜底) return apiService.fetchPois(lat, lng).also { memoryCache.put("$lat,$lng", it) } }参数说明:geohash(lat, lng, 5)生成5位GeoHash编码,将地球表面划分为约4.9km×4.9km网格,每个网格对应一个JSON文件,降低文件碎片化。
5.2 拜访决策页的动态信息聚合
点击某个POI进入详情页时,MOMA并非静态展示数据,而是实时聚合多源信息:
| 数据源 | 聚合内容 | 更新频率 | 技术实现 |
|---|---|---|---|
| CRM核心服务 | POI基础信息、私海状态、最近拜访记录 | 实时 | WebSocket长连接 |
| MDC大数据 | 近7天销量趋势图、用户复购率 | T+1 | 本地预加载图表模板 |
| 竞对API | 该POI在饿了么/大众点评的在线状态、价格 | 5分钟 | 后台Service Worker轮询 |
关键交互逻辑:当BD在详情页点击“发起拜访”按钮时,系统自动执行:
- 校验BD是否在该POI 500米范围内(GPS精度±10米)
- 若距离超限,弹窗提示:“请靠近门店再提交,确保拜访真实性”
- 提交时强制拍摄门店门头照(调用相机API,照片含GPS水印)
- 照片上传至CDN后,异步触发OCR识别门头文字,与POI名称比对(相似度<80%则标记为“疑似非目标门店”)
5.3 离线模式下的任务保活机制
BD常处于地铁、地下商场等弱网环境。MOMA设计离线任务队列:
- 所有操作(拜访记录、任务反馈、合同签署)先写入本地SQLite
- 网络恢复时,按时间戳顺序批量同步至CRM服务端
- 同步失败的任务进入重试队列(指数退避:1s→2s→4s→8s)
- 若连续3次失败,自动切换至“离线模式”,仅允许查看已缓存数据,禁用提交操作
-- 本地SQLite任务队列表结构 CREATE TABLE offline_tasks ( id INTEGER PRIMARY KEY AUTOINCREMENT, type TEXT NOT NULL, -- 'visit', 'task_feedback', 'contract_sign' payload TEXT NOT NULL, -- JSON序列化数据 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, sync_status TEXT DEFAULT 'pending', -- pending/syncing/success/failed retry_count INTEGER DEFAULT 0, last_retry_time TIMESTAMP );关键技巧:为避免离线数据冲突,所有本地操作使用
tenant_id+device_id作为唯一标识符。当BD更换手机登录时,系统自动合并历史离线任务,按created_at时间戳去重——这保证了即使设备丢失,业务数据也不会永久丢失。
本文还有配套的精品资源,点击获取