Steve Trucking,如果由我来设计
另有 28 种语言版本
English · Español · 日本語 · Português (Brasil) · Français · Deutsch · Italiano · 한국어 · Português (Portugal) · 繁體中文 · Bahasa Indonesia · Türkçe · Polski · Tiếng Việt · ไทย · Nederlands · العربية · עברית · Українська · हिन्दी · Русский · Svenska · Dansk · Norsk bokmål · Suomi · Español (México) · Français (Canada) · Deutsch (Schweiz)

第 6 个模块,共 6 个,属于 Data Architect 课程第 6 章主数据与身份,也是第 1 部分的结尾。 上一篇:当权威被共享 · 下一篇:第 2 部分从Designing for Scale *(coming soon)*开始
**本检查点回答的问题:**你能在一个真实的情景中把第 1 部分串起来吗?
**先尝试挑战。**这是我对检查点 1 挑战的讲解。如果你还没有画出自己的设计,在继续读之前先去画。价值在于把你的推理和我的进行比较,而不在于读答案。
这是“如果由我来设计”:一个可行的方案,而不是唯一的答案,其中的权衡都已点明,我的立场也已表明。我们还没有讲大数据量、查询设计、集成模式、迁移或事务,这是有意的:架构会随着你学到更多而发展。但第 1 部分给了我们足够的东西来搭好骨架。
从数字开始
Section titled “从数字开始 ”来自简介:每个工作日大约 3,300 次配送,每年一百万次,每年增长 30%。每次配送大约 1.6 个行项目(每年 160 万个);每次配送大约八次状态变更(每年 800 万次);每年四五百万张照片;每天大约 20 万条 GPS 读数;每年大约 18 万个个案;三个零售合作伙伴用三种不同的方式发送装货清单;九个配送中心;330 辆卡车,配两人小组。而且 Steve Trucking 已经在运行一个 Salesforce org,有 Service Cloud、Field Service 和一个合作伙伴门户。在画任何一个方框之前,先数零。它们会决定下面好几件事。
配送核心:看向母舰
Section titled “配送核心:看向母舰 ”配送是核心,而 Field Service 已经在做调度了。所以我从 Field Service 的标准模型开始,就像第 3 章的那个切面一样:
| 业务概念 | Salesforce 对象 | 原因 |
|---|---|---|
| 零售合作伙伴 | 客户(Account)(零售合作伙伴记录类型) | Steve Trucking 与之签约的企业;承载合同、个案和门户访问 |
| 合作伙伴员工(配送中心经理、门店员工) | 联系人(Contact) | 门户用户必须是联系人 |
| 一次配送:一位收货人、一个地址、一个合作伙伴订单、一天 | 工作订单(Work Order) | Field Service 的工作单位;排期、移动应用和服务报告都挂在它上面 |
| 每件商品或服务:冰箱、安装、拉走旧货 | 工作订单行项目(Work Order Line Item) | 划分工作,驱动检查清单和开票 |
| 停靠点类型:仅配送、加安装、加拉走旧货 | 工作类型(Work Type) | 设定时长、技能和安装检查清单 |
| 排定的上门服务及其时间窗口 | 服务预约(Service Appointment) | Field Service 排期的对象,也是配送小组的应用里显示的东西 |
| 配送小组和卡车;配送中心的调度区域 | 服务资源、服务小组、服务区域(Service Resource、Service Crew、Service Territory) | Field Service 把一个配送小组作为一个资源来排期 |
| 收货人的咨询、合作伙伴的索赔 | 个案(Case) | 服务控制台、权利、电子邮件转个案 |
| 合作伙伴在凤凰城配送中心周二的那份清单 | Manifest__c(自定义) | 没有标准对象能表示接收、对账和重放的单位 |
其他一切都保持标准。抵制更多的自定义对象是有意的:第 1 章的问题是架构师什么时候应该抵制再加一个,而在这里答案是“几乎总是”。比如,合作伙伴的订单行就不是一个新对象。它就是工作订单,由合作伙伴的编号来识别。
它由第 3 章的最终图(设计 Salesforce 物理模型)发展而来:同样的对象在同样的位置,再加上配送小组、调度区域、个案,以及检查点 1 放在核心之外的东西。
把合作伙伴的订单与配送匹配起来的键
Section titled “把合作伙伴的订单与配送匹配起来的键 ”每一行装货清单都变成一个工作订单,并链接到它的装货清单。键是我最想得到回答的问题:我们怎么知道合作伙伴的这一行就是那一次配送?我的答案是:工作订单上的一个外部 ID,由零售合作伙伴加上合作伙伴自己的订单和配送编号组成(类似 KEYSTONE-PHX-8843119-1),标记为唯一。每个来源一个字段,一一对应。它是合作伙伴的标识符,而不是我们的:这是第 2 章的“一样东西,好几个标识符”,也是模块 1 的“合作伙伴拥有它的订单编号”。
为什么这很重要:装货清单提前一到两天到达,并会在当天修改。有了这个键,每一份重发或修改后的装货清单都会做 upsert,而不是产生重复。修改会更新工作订单,一个字段记录下这次修改,而对一次已经排好路线的配送的修改会提醒协调员:合作伙伴的修改被应用了,但在调度确认之前会被标记出来。这也是与第 4 章那张图相比发生变化的地方。如今每一份装货清单都先进入 RouteDesk,协调员再把路线重新录入 Salesforce,并把已完成的停靠点录回去。在这个设计中,装货清单直接进入 Salesforce,按合作伙伴的键做 upsert;RouteDesk 退役,重复录入也就结束了。集成那一章会设计三种入站格式。数据层面的决定就是这个键。
收货人:个人客户、联系人,还是都不是?
Section titled “收货人:个人客户、联系人,还是都不是? ”这是第 1 部分中最有意思的数据决定,所以这里先列出选项,再给出我的选择。
选项 A:个人客户。每位收货人成为一个个人客户,链接到每一次配送。*支持的理由:*标准,能与 Service Cloud、消息和控制台自然配合,能识别重复的收货人。*反对的理由:*每年大约一百万位新收货人,每一位都是一个个人客户,存储大约是企业客户的两倍(Estimated Record Size by Object Type (opens in a new tab),英文),所以两年内就会成为 org 中最大的对象之一。而且收货人不是 Steve Trucking 的客户。他们是每个零售合作伙伴的客户,而 Steve Trucking 绝不能把一个合作伙伴的客户和另一个合作伙伴的客户混在一起(S2)。
**选项 B:零售合作伙伴客户下的联系人。***反对的理由:*三四个客户下面挂一百万个联系人,是大规模的父子数据倾斜,远远超过 Salesforce 关于每个父记录大约 10,000 条子记录的建议(Considerations for Object Relationships (opens in a new tab);Parent-Child Data Skew (opens in a new tab),英文)。这是一个需要展示出来、然后否决的选项。
选项 C:收货人信息放在配送上。收货人的姓名、电话、电子邮件、地址和配送备注是工作订单上的字段(地址字段在那里本来就是标准字段),从装货清单中采集。*支持的理由:*没有新的大对象;数据的存在时间恰好与配送所需的一样长;删除按每次配送、按合作伙伴的时间表进行;而合作伙伴隔离是自然而然的,因为每次配送只属于一个合作伙伴。*反对的理由:*重复的收货人不会被识别为同一个人。
这就是需要把握的平衡。是否会有需要把好几次配送识别为同一个人、在同一个地点?是否要给这个人一个登录账号?这就是两种情况的分界线:一种是收货人需要一条属于自己的记录,另一种是收货人信息只是关于这次配送的数据。而且还有一条折中的路。把零售合作伙伴自己的客户 ID 作为配送上的一个字段,即零售合作伙伴客户 ID(Retail Partner Customer ID)。它不会创建收货人记录,但能把一个合作伙伴为同一位客户发来的多次配送串在一起,这是更统一的客户体验的起点,而且它直接指回零售合作伙伴的系统,也就是那位客户真正所在的地方。这是合作伙伴的标识符,所以它只有和合作伙伴放在一起才有意义:一个合作伙伴的客户 4417 和另一个合作伙伴的客户 4417 毫无关系。
依我的专业判断,选项 C 是正确的选择。不能识别重复这一点是可以接受的,甚至是可取的:除了这次配送,Steve Trucking 和这些人没有任何关系。这又是模块 1:收货人是合作伙伴的客户,而合作伙伴是他们身份的权威。这也是第 5 章:落在一个地方、与一次配送绑定的个人数据,保护、保留和删除起来都要容易得多。而且它也经得起第 2 章范式的检验:收货人的信息与配送是一对一的,所以它们属于配送。一个单独的收货人子对象能省下几个重复的值,代价却是多一个对象、多一个关系以及随之而来的开销;而它唯一能省下更多的方式,是把跨零售合作伙伴的同一个人当作一个人,而我们不会这么做。所以由配送承载收货人信息,再用零售合作伙伴客户 ID 指回合作伙伴自己的系统。
我会跨合作伙伴统一收货人吗?
Section titled “我会跨合作伙伴统一收货人吗? ”John Smith,123 Main Street,同时出现在 Redrock 和 Brightwave 的装货清单中。多半是同一个人。Steve Trucking 应该统一他们吗?**不,有意不统一。**跨零售合作伙伴统一收货人会违反 S2:一个合作伙伴绝不能看到另一个合作伙伴的收货人,而一个统一的身份恰恰就是那座会泄露信息的桥。这正是本章立场的运用:在混合代价高昂的地方少匹配,而在这里,混合的代价非常高。
如果某个零售合作伙伴以后希望在它自己的配送范围内识别重复的收货人,那是限定在该合作伙伴范围内的身份解析工具(比如 Data 360 的身份解析)的工作:一张注册式的地图,而不是一个个人客户,而且永远不跨合作伙伴。一张谁是谁的地图不授予所有权,也不授予访问权限。
什么留在 org 里,什么不留
Section titled “什么留在 org 里,什么不留 ”第 3 章问的是数据应该放在哪里。在这里,零的个数给出了答案:
- 当前状态放在服务预约和工作订单上。状态变更的历史,每年大约 800 万次,而且还在增长,不需要放在核心 org 里。每次变更都作为一个事件发布出去,保存在数据仓库 Snowflake 中。org 保留当前状态;历史仍然可供服务、运营和分析使用,只是不在运营数据库里。
- 照片(每年四五百万张,有些拍到了人或住宅内部)放在核心平台之外为这种数据量而构建的存储中,直接从配送小组的应用上传。org 只保留它需要的东西:每张照片一条小小的索引记录,或者只是一个数量和一个“所需安装照片已齐全”的标志。我更倾向于较轻的那种:让 org 保持精简,由照片存储自己拥有它的索引和保留策略。
- GPS 读数(每天 20 万条)留在 FleetLink 中,并进入 Snowflake;org 只需要最新的位置,供跟踪页面和调度员的地图使用。
- RouteDesk 八年的历史(大约 500 万次配送)进入数据仓库或档案库,供索赔时查阅。哪些数据(如果有的话)要进入 org,是第 2 部分的一个迁移决定。
检查点 1:如果由我来设计。与第 4 章全景图(Steve Trucking 的全景图)的位置相同,只是重复录入和电子表格都不见了。
谁看到什么,谁需要许可
Section titled “谁看到什么,谁需要许可 ”- 零售合作伙伴只看到自己的配送(S2)。每个工作订单都带有它的零售合作伙伴;门户用户看到他们合作伙伴的配送,配送中心经理只看到自己配送中心的。
- 合作伙伴用户需要一个支持共享规则和角色的门户许可:Customer Community Plus 或 Partner Community。第 3 章的体育场座位:最便宜的座位得不到这个设计所需的共享。这两种许可都需要为外部用户设置角色,而 Salesforce 警告说,角色越多,org 越慢(Experience Cloud User Licenses (opens in a new tab),英文)。每个合作伙伴、每个配送中心一个角色没有问题;每家门店一个角色就不行了。
考点。掌握哪些外部许可支持标准共享:Customer Community Plus 和 Partner Community(需要为外部用户设置角色),而不是使用共享集的 Customer Community。
- **收货人不需要许可。**跟踪页面通过一个带有会过期的令牌的链接显示一次配送(S3),而不是通过登录。
- **留意数据倾斜。**每年几十万个工作订单指向三四个合作伙伴客户,就是客户数据倾斜。一个选项是在每个合作伙伴下为每个配送中心建一个子客户,把子记录分散到九个或更多的父记录下;在索赔期结束后归档已完成的配送,能让每个父记录下的活跃子记录保持在较低水平。第 2 部分会处理这个问题。
我不会做的事
Section titled “我不会做的事 ”我不会因为收货人是个人,就为每位收货人创建一个个人客户。我不会在三个客户下面挂一百万个联系人。我不会在 Field Service 的工作订单旁边再建一个自定义的配送对象。我不会跨合作伙伴统一收货人。我不会把几百万张照片或 GPS 读数放进核心存储。而且除非我们真的做出了主控决定,否则我不会把一个统一的收货人叫作黄金记录。
仍然未决的问题
Section titled “仍然未决的问题 ”第 1 部分搭好了骨架;第 2 部分来检验它。第三年的大数据量标尺(工作订单、服务预约和行项目在两三年内都会进入大数据量的范畴),针对合作伙伴范围的列表视图的查询设计,三个入站集成和三个状态回传,RouteDesk 的迁移,当天的事务,以及门户背后的安全设计。Steve Trucking 也会变化。保留这个设计;你还会回来重新审视它。
架构师在这里决定什么
Section titled “架构师在这里决定什么 ”- 哪些标准对象承载核心(这里是 Field Service 的),哪些自定义对象确实有理由存在(这里是一个)。
- 把每个合作伙伴的订单行与一次配送匹配起来的键,以及为什么它属于合作伙伴。
- 收货人是什么,依据的是 Steve Trucking 与他们之间实际存在的关系。
- 是否统一身份,以及在哪里混合的代价太高而不值得冒险。
- 什么留在 org 里,什么放在核心平台之外,以及设计依赖哪些许可。
- Steve Trucking 的简介和挑战(D1、D3、DC1)。
- Salesforce Help,Salesforce Data Storage: Estimated Record Size by Object Type (opens in a new tab)、Considerations for Object Relationships (opens in a new tab) 和 Experience Cloud User Licenses (opens in a new tab)(英文),查阅日期 2026-10-14。
- Salesforce Developers,Parent-Child Data Skew (opens in a new tab)(英文),第 3 章中引用过。
