{
  "type": "excalidraw",
  "version": 2,
  "source": "https://excalidraw.com",
  "elements": [
    {
      "type": "text",
      "version": 1,
      "versionNonce": 1,
      "isDeleted": false,
      "id": "title-main",
      "fillStyle": "solid",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 0,
      "opacity": 100,
      "angle": 0,
      "x": 600,
      "y": 50,
      "strokeColor": "#1e1e1e",
      "backgroundColor": "transparent",
      "width": 800,
      "height": 45,
      "seed": 1,
      "groupIds": [],
      "frameId": null,
      "roundness": null,
      "boundElements": [],
      "updated": 1,
      "link": null,
      "locked": false,
      "fontSize": 36,
      "fontFamily": 1,
      "text": "多品类统一商品上架系统架构",
      "textAlign": "center",
      "verticalAlign": "top",
      "containerId": null,
      "originalText": "多品类统一商品上架系统架构",
      "lineHeight": 1.25,
      "baseline": 32
    },
    {
      "type": "rectangle",
      "version": 1,
      "versionNonce": 1,
      "isDeleted": false,
      "id": "layer1-box",
      "fillStyle": "solid",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 0,
      "opacity": 100,
      "angle": 0,
      "x": 100,
      "y": 150,
      "strokeColor": "#1971c2",
      "backgroundColor": "#d0ebff",
      "width": 1600,
      "height": 200,
      "seed": 1,
      "groupIds": [],
      "frameId": null,
      "roundness": null,
      "boundElements": [],
      "updated": 1,
      "link": null,
      "locked": false
    },
    {
      "type": "text",
      "version": 1,
      "versionNonce": 1,
      "isDeleted": false,
      "id": "layer1-title",
      "fillStyle": "solid",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 0,
      "opacity": 100,
      "angle": 0,
      "x": 120,
      "y": 165,
      "strokeColor": "#1e1e1e",
      "backgroundColor": "transparent",
      "width": 250,
      "height": 35,
      "seed": 1,
      "groupIds": [],
      "frameId": null,
      "roundness": null,
      "boundElements": [],
      "updated": 1,
      "link": null,
      "locked": false,
      "fontSize": 28,
      "fontFamily": 1,
      "text": "📥 数据入口层",
      "textAlign": "left",
      "verticalAlign": "top",
      "containerId": null,
      "originalText": "📥 数据入口层",
      "lineHeight": 1.25,
      "baseline": 25
    },
    {
      "type": "rectangle",
      "version": 1,
      "versionNonce": 1,
      "isDeleted": false,
      "id": "entry1",
      "fillStyle": "solid",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 0,
      "opacity": 100,
      "angle": 0,
      "x": 140,
      "y": 220,
      "strokeColor": "#2f9e44",
      "backgroundColor": "#d3f9d8",
      "width": 220,
      "height": 100,
      "seed": 1,
      "groupIds": [],
      "frameId": null,
      "roundness": { "type": 3 },
      "boundElements": [{ "type": "text", "id": "entry1-text" }],
      "updated": 1,
      "link": null,
      "locked": false
    },
    {
      "type": "text",
      "version": 1,
      "versionNonce": 1,
      "isDeleted": false,
      "id": "entry1-text",
      "fillStyle": "solid",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 0,
      "opacity": 100,
      "angle": 0,
      "x": 155,
      "y": 235,
      "strokeColor": "#1e1e1e",
      "backgroundColor": "transparent",
      "width": 190,
      "height": 70,
      "seed": 1,
      "groupIds": [],
      "frameId": null,
      "roundness": null,
      "boundElements": [],
      "updated": 1,
      "link": null,
      "locked": false,
      "fontSize": 16,
      "fontFamily": 1,
      "text": "运营上传\n• 表单/Excel批量\n• 免审核\n• 快速通道",
      "textAlign": "left",
      "verticalAlign": "top",
      "containerId": "entry1",
      "originalText": "运营上传\n• 表单/Excel批量\n• 免审核\n• 快速通道",
      "lineHeight": 1.25,
      "baseline": 62
    },
    {
      "type": "rectangle",
      "version": 1,
      "versionNonce": 1,
      "isDeleted": false,
      "id": "entry2",
      "fillStyle": "solid",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 0,
      "opacity": 100,
      "angle": 0,
      "x": 390,
      "y": 220,
      "strokeColor": "#f08c00",
      "backgroundColor": "#ffe8cc",
      "width": 220,
      "height": 100,
      "seed": 1,
      "groupIds": [],
      "frameId": null,
      "roundness": { "type": 3 },
      "boundElements": [{ "type": "text", "id": "entry2-text" }],
      "updated": 1,
      "link": null,
      "locked": false
    },
    {
      "type": "text",
      "version": 1,
      "versionNonce": 1,
      "isDeleted": false,
      "id": "entry2-text",
      "fillStyle": "solid",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 0,
      "opacity": 100,
      "angle": 0,
      "x": 405,
      "y": 235,
      "strokeColor": "#1e1e1e",
      "backgroundColor": "transparent",
      "width": 190,
      "height": 70,
      "seed": 1,
      "groupIds": [],
      "frameId": null,
      "roundness": null,
      "boundElements": [],
      "updated": 1,
      "link": null,
      "locked": false,
      "fontSize": 16,
      "fontFamily": 1,
      "text": "商家上传\n• Portal/App\n• 人工审核\n• 限流保护",
      "textAlign": "left",
      "verticalAlign": "top",
      "containerId": "entry2",
      "originalText": "商家上传\n• Portal/App\n• 人工审核\n• 限流保护",
      "lineHeight": 1.25,
      "baseline": 62
    },
    {
      "type": "rectangle",
      "version": 1,
      "versionNonce": 1,
      "isDeleted": false,
      "id": "entry3",
      "fillStyle": "solid",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 0,
      "opacity": 100,
      "angle": 0,
      "x": 640,
      "y": 220,
      "strokeColor": "#9c36b5",
      "backgroundColor": "#f3d9fa",
      "width": 220,
      "height": 100,
      "seed": 1,
      "groupIds": [],
      "frameId": null,
      "roundness": { "type": 3 },
      "boundElements": [{ "type": "text", "id": "entry3-text" }],
      "updated": 1,
      "link": null,
      "locked": false
    },
    {
      "type": "text",
      "version": 1,
      "versionNonce": 1,
      "isDeleted": false,
      "id": "entry3-text",
      "fillStyle": "solid",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 0,
      "opacity": 100,
      "angle": 0,
      "x": 655,
      "y": 235,
      "strokeColor": "#1e1e1e",
      "backgroundColor": "transparent",
      "width": 190,
      "height": 70,
      "seed": 1,
      "groupIds": [],
      "frameId": null,
      "roundness": null,
      "boundElements": [],
      "updated": 1,
      "link": null,
      "locked": false,
      "fontSize": 16,
      "fontFamily": 1,
      "text": "批量导入\n• Excel/CSV\n• OSS存储\n• 流式解析防OOM",
      "textAlign": "left",
      "verticalAlign": "top",
      "containerId": "entry3",
      "originalText": "批量导入\n• Excel/CSV\n• OSS存储\n• 流式解析防OOM",
      "lineHeight": 1.25,
      "baseline": 62
    },
    {
      "type": "rectangle",
      "version": 1,
      "versionNonce": 1,
      "isDeleted": false,
      "id": "entry4",
      "fillStyle": "solid",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 0,
      "opacity": 100,
      "angle": 0,
      "x": 890,
      "y": 220,
      "strokeColor": "#e03131",
      "backgroundColor": "#ffe3e3",
      "width": 220,
      "height": 100,
      "seed": 1,
      "groupIds": [],
      "frameId": null,
      "roundness": { "type": 3 },
      "boundElements": [{ "type": "text", "id": "entry4-text" }],
      "updated": 1,
      "link": null,
      "locked": false
    },
    {
      "type": "text",
      "version": 1,
      "versionNonce": 1,
      "isDeleted": false,
      "id": "entry4-text",
      "fillStyle": "solid",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 0,
      "opacity": 100,
      "angle": 0,
      "x": 905,
      "y": 235,
      "strokeColor": "#1e1e1e",
      "backgroundColor": "transparent",
      "width": 190,
      "height": 70,
      "seed": 1,
      "groupIds": [],
      "frameId": null,
      "roundness": null,
      "boundElements": [],
      "updated": 1,
      "link": null,
      "locked": false,
      "fontSize": 16,
      "fontFamily": 1,
      "text": "供应商Push\n• MQ实时推送\n• 快速通道\n• 毫秒级响应",
      "textAlign": "left",
      "verticalAlign": "top",
      "containerId": "entry4",
      "originalText": "供应商Push\n• MQ实时推送\n• 快速通道\n• 毫秒级响应",
      "lineHeight": 1.25,
      "baseline": 62
    },
    {
      "type": "rectangle",
      "version": 1,
      "versionNonce": 1,
      "isDeleted": false,
      "id": "entry5",
      "fillStyle": "solid",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 0,
      "opacity": 100,
      "angle": 0,
      "x": 1140,
      "y": 220,
      "strokeColor": "#e03131",
      "backgroundColor": "#ffe3e3",
      "width": 220,
      "height": 100,
      "seed": 1,
      "groupIds": [],
      "frameId": null,
      "roundness": { "type": 3 },
      "boundElements": [{ "type": "text", "id": "entry5-text" }],
      "updated": 1,
      "link": null,
      "locked": false
    },
    {
      "type": "text",
      "version": 1,
      "versionNonce": 1,
      "isDeleted": false,
      "id": "entry5-text",
      "fillStyle": "solid",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 0,
      "opacity": 100,
      "angle": 0,
      "x": 1155,
      "y": 235,
      "strokeColor": "#1e1e1e",
      "backgroundColor": "transparent",
      "width": 190,
      "height": 70,
      "seed": 1,
      "groupIds": [],
      "frameId": null,
      "roundness": null,
      "boundElements": [],
      "updated": 1,
      "link": null,
      "locked": false,
      "fontSize": 16,
      "fontFamily": 1,
      "text": "供应商Pull\n• 定时拉取API\n• 增量同步\n• 分钟级更新",
      "textAlign": "left",
      "verticalAlign": "top",
      "containerId": "entry5",
      "originalText": "供应商Pull\n• 定时拉取API\n• 增量同步\n• 分钟级更新",
      "lineHeight": 1.25,
      "baseline": 62
    },
    {
      "type": "rectangle",
      "version": 1,
      "versionNonce": 1,
      "isDeleted": false,
      "id": "entry6",
      "fillStyle": "solid",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 0,
      "opacity": 100,
      "angle": 0,
      "x": 1390,
      "y": 220,
      "strokeColor": "#1098ad",
      "backgroundColor": "#c5f6fa",
      "width": 220,
      "height": 100,
      "seed": 1,
      "groupIds": [],
      "frameId": null,
      "roundness": { "type": 3 },
      "boundElements": [{ "type": "text", "id": "entry6-text" }],
      "updated": 1,
      "link": null,
      "locked": false
    },
    {
      "type": "text",
      "version": 1,
      "versionNonce": 1,
      "isDeleted": false,
      "id": "entry6-text",
      "fillStyle": "solid",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 0,
      "opacity": 100,
      "angle": 0,
      "x": 1405,
      "y": 235,
      "strokeColor": "#1e1e1e",
      "backgroundColor": "transparent",
      "width": 190,
      "height": 70,
      "seed": 1,
      "groupIds": [],
      "frameId": null,
      "roundness": null,
      "boundElements": [],
      "updated": 1,
      "link": null,
      "locked": false,
      "fontSize": 16,
      "fontFamily": 1,
      "text": "API接口\n• RPC/REST\n• 按来源配置\n• 幂等保证",
      "textAlign": "left",
      "verticalAlign": "top",
      "containerId": "entry6",
      "originalText": "API接口\n• RPC/REST\n• 按来源配置\n• 幂等保证",
      "lineHeight": 1.25,
      "baseline": 62
    },
    {
      "type": "text",
      "version": 1,
      "versionNonce": 1,
      "isDeleted": false,
      "id": "core-tech-summary",
      "fillStyle": "solid",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 0,
      "opacity": 100,
      "angle": 0,
      "x": 100,
      "y": 400,
      "strokeColor": "#1e1e1e",
      "backgroundColor": "transparent",
      "width": 1600,
      "height": 900,
      "seed": 1,
      "groupIds": [],
      "frameId": null,
      "roundness": null,
      "boundElements": [],
      "updated": 1,
      "link": null,
      "locked": false,
      "fontSize": 18,
      "fontFamily": 1,
      "text": "🔑 核心技术架构要点：\n\n⚙️ Service层: ListingUploadService\n  • 数据校验（必填项、格式、业务规则） • 雪花算法生成task_code • 乐观锁+唯一索引\n  • 审核策略路由（根据source_type选择通道） • 返回task_code异步处理\n\n🔄 Kafka异步队列（5个Topic）:\n  listing.batch.created → ExcelParseWorker | listing.audit.pending → AuditWorker\n  listing.publish.ready → PublishWorker | listing.published → ES同步/缓存刷新\n  *.dlq → 死信队列（消费失败3次后人工介入）\n\n⚡ Async Workers层（6个Worker）:\n  1. ExcelParseWorker: 流式解析、逐行校验、100条/批、防OOM\n  2. AuditWorker: 规则引擎校验、策略路由、乐观锁更新、人工审核推送\n  3. PublishWorker: Saga事务编排、创建item/sku、本地消息表、补偿机制\n  4. WatchdogWorker: 超时监控、自动重试、指数退避、失败告警\n  5. OutboxPublisher: 轮询本地消息表、可靠事件发布、最终一致性\n  6. SupplierSyncWorker: 定时拉取、增量同步、批量导入\n\n🔄 统一状态机: DRAFT(0) → Pending(10) → Approved(11) → Online(20) / Rejected(12)\n\n🔀 Saga分布式事务（8步骤）:\n  1.CreateItem → 2.CreateSKU → 3.CreateAttributes → 4.CreatePrice\n  5.UpdateStatus → 6.PublishEvent(Outbox) → 7.UpdateCache → 8.SyncES\n  • 任一步骤失败→逆序补偿回滚 • 状态持久化 • 支持断点恢复\n\n💾 数据持久化层:\n  • MySQL分库分表: 按category_id取模(16张表) + 按月归档\n  • Redis缓存: L1本地(1min)+L2Redis(5min)双层缓存、分布式锁、限流\n  • Elasticsearch: 全文搜索、历史查询、日志分析、实时统计\n  • OSS: Excel文件、结果文件、商品图片、券码文件\n  • Outbox本地消息表: 与业务同库事务、异步发布Kafka、最终一致性\n\n📊 监控告警:\n  • Prometheus: task成功率、耗时、队列长度、Saga执行、Outbox状态\n  • Grafana: 实时大盘、品类分布、Worker处理能力、数据库连接池\n  • 告警: 成功率<90% | 耗时>10min | 积压>5000 | Saga补偿失败\n\n🎯 17个核心技术点:\n  统一状态机 | 数据来源驱动审核 | 策略模式 | 异步化 | 并发安全(乐观锁+唯一索引)\n  分库分表 | 软删除+归档 | Saga事务 | Outbox Pattern | 看门狗机制 | 限流熔断\n  幂等保证 | 流式处理 | 多级缓存 | 死信队列 | 灰度发布 | 完整监控",
      "textAlign": "left",
      "verticalAlign": "top",
      "containerId": null,
      "originalText": "🔑 核心技术架构要点：\n\n⚙️ Service层: ListingUploadService\n  • 数据校验（必填项、格式、业务规则） • 雪花算法生成task_code • 乐观锁+唯一索引\n  • 审核策略路由（根据source_type选择通道） • 返回task_code异步处理\n\n🔄 Kafka异步队列（5个Topic）:\n  listing.batch.created → ExcelParseWorker | listing.audit.pending → AuditWorker\n  listing.publish.ready → PublishWorker | listing.published → ES同步/缓存刷新\n  *.dlq → 死信队列（消费失败3次后人工介入）\n\n⚡ Async Workers层（6个Worker）:\n  1. ExcelParseWorker: 流式解析、逐行校验、100条/批、防OOM\n  2. AuditWorker: 规则引擎校验、策略路由、乐观锁更新、人工审核推送\n  3. PublishWorker: Saga事务编排、创建item/sku、本地消息表、补偿机制\n  4. WatchdogWorker: 超时监控、自动重试、指数退避、失败告警\n  5. OutboxPublisher: 轮询本地消息表、可靠事件发布、最终一致性\n  6. SupplierSyncWorker: 定时拉取、增量同步、批量导入\n\n🔄 统一状态机: DRAFT(0) → Pending(10) → Approved(11) → Online(20) / Rejected(12)\n\n🔀 Saga分布式事务（8步骤）:\n  1.CreateItem → 2.CreateSKU → 3.CreateAttributes → 4.CreatePrice\n  5.UpdateStatus → 6.PublishEvent(Outbox) → 7.UpdateCache → 8.SyncES\n  • 任一步骤失败→逆序补偿回滚 • 状态持久化 • 支持断点恢复\n\n💾 数据持久化层:\n  • MySQL分库分表: 按category_id取模(16张表) + 按月归档\n  • Redis缓存: L1本地(1min)+L2Redis(5min)双层缓存、分布式锁、限流\n  • Elasticsearch: 全文搜索、历史查询、日志分析、实时统计\n  • OSS: Excel文件、结果文件、商品图片、券码文件\n  • Outbox本地消息表: 与业务同库事务、异步发布Kafka、最终一致性\n\n📊 监控告警:\n  • Prometheus: task成功率、耗时、队列长度、Saga执行、Outbox状态\n  • Grafana: 实时大盘、品类分布、Worker处理能力、数据库连接池\n  • 告警: 成功率<90% | 耗时>10min | 积压>5000 | Saga补偿失败\n\n🎯 17个核心技术点:\n  统一状态机 | 数据来源驱动审核 | 策略模式 | 异步化 | 并发安全(乐观锁+唯一索引)\n  分库分表 | 软删除+归档 | Saga事务 | Outbox Pattern | 看门狗机制 | 限流熔断\n  幂等保证 | 流式处理 | 多级缓存 | 死信队列 | 灰度发布 | 完整监控",
      "lineHeight": 1.25,
      "baseline": 890
    }
  ],
  "appState": {
    "gridSize": null,
    "viewBackgroundColor": "#ffffff"
  },
  "files": {}
}
