项目背景:200家门店的”系统拼图”

茶语是一家拥有200+门店的连锁茶饮品牌。找到我们的时候,他们的IT系统是一幅典型的”拼图”:

  • 门店端:有一套第三方的点单小程序,但数据存在供应商那边,想改个会员规则要排期两周;
  • 设备端:制冰机、开水器、智能茶桶分别来自三个厂家,各有各的APP,店长手机上装了5个设备管理软件;
  • 总部端:ERP、财务系统、人事系统各跑各的,想看个”单店日均出杯量”得从三个系统导数据拼。

老板的诉求很直接:能不能用一套系统把这些都管起来?

这就是典型的中台建设场景。但中台不是买个架子往上挂就行,真正难的是”打通”——把异构系统、异构设备、异构数据全部揉到一个体系里。

核心挑战:三个”不一样”

在动手之前,我们先盘了一下要面对的问题,总结为三个”不一样”:

1. 终端协议不一样

5种设备,5种协议:智能茶桶走MQTT,制冰机走Modbus RTU,开水器是厂商私有HTTP接口,POS机是串口打印数据,还有一套老的温控系统走的是TCP自定义协议。

如果每个设备都单独写对接代码,那就是5套逻辑,以后加新设备还要再写,维护成本爆炸。

2. 数据格式不一样

同样是”温度”这个指标,茶桶上报的是 {device_id: "xxx", temp: 85.5, ts: 1655...},制冰机上报的是 ["IC-001", "TANK", -5.2, "2023-06-15 14:30:00"],字段名、数据类型、时间格式全不一样。

3. 业务口径不一样

门店小程序里的”订单数”和ERP里的”订单数”不是一个数——小程序里包含了已取消的订单,ERP里只统计已完成的。类似的口径差异有十几个,这也是为什么总部报表总是对不上的原因。

中台架构设计:分层解耦

针对这三个问题,我们的中台架构做了分层设计:

┌─────────────────────────────────────────────────┐
│                   应用层                         │
│  门店小程序 / 总部管理后台 / 数据分析平台          │
├─────────────────────────────────────────────────┤
│                   服务层                         │
│  订单服务 / 会员服务 / 设备服务 / 库存服务         │
│  (统一API网关 + 统一数据模型)                   │
├─────────────────────────────────────────────────┤
│                   接入层                         │
│  协议适配网关 / 消息队列 / 数据清洗引擎            │
│  MQTT / Modbus / HTTP / TCP 自定义               │
├─────────────────────────────────────────────────┤
│                   数据层                         │
│  时序数据库(设备数据)/ 关系数据库(业务数据)     │
└─────────────────────────────────────────────────┘

关键设计思路有三个:

1. 接入层:协议转换 + 统一消息格式

我们在接入层做了一个协议适配网关,所有设备数据进来后,先转换成统一的JSON消息格式,再发到消息队列里。

举个例子,制冰机的Modbus数据进来后,网关会把它转成:

{
  "device_id": "IC-001",
  "metric": "tank_temp",
  "value": -5.2,
  "timestamp": 1686810600,
  "unit": "celsius"
}

这样,上层的设备服务只需要处理一种格式的数据。以后加新设备,只要在接入层加个适配器就行,上层完全不用改。

2. 服务层:领域模型 + 统一口径

服务层按照领域驱动设计(DDD)的思路,把业务拆成了订单、会员、设备、库存等几个核心服务。每个服务有自己的数据库,但对外提供统一的API。

这里最关键的是数据口径的统一。我们花了整整一周时间,和茶语的运营、财务、门店运营一起,把所有核心指标的定义重新梳理了一遍,形成了一份”数据字典”。比如”订单数”明确定义为”已支付且未退款的订单数量”,所有系统都按这个口径来。

3. 数据层:冷热分离

设备数据和业务数据的特征完全不一样:

  • 设备数据:量大(200店×5设备×每30秒一条 = 每天近300万条)、写多读少、时序特征明显;
  • 业务数据:量小(每天几万条订单)、读写均衡、关系复杂。

所以我们用了混合存储:设备数据进时序数据库(TDengine),业务数据进关系数据库(PostgreSQL)。需要联合分析的时候,通过服务层做聚合,而不是硬塞到一个库里。

落地踩坑与解法

说几个项目过程中印象比较深的坑:

坑1:设备数据量远超预期

上线第一周,我们发现实际数据量是预估的3倍——原来有些设备的上报频率不是30秒一次,而是5秒一次。时序数据库的写入压力瞬间上来了。

解法:在接入层加了一层边缘聚合。边缘网关本地先做降采样,比如5秒粒度的数据在本地存,上报的时候按1分钟聚合上报。需要细查的时候,再从网关本地拉取。这样上报量直接降到原来的1/12。

坑2:老系统数据迁移的”脏数据”

从老ERP迁移历史数据的时候,我们发现了大量脏数据:同一个门店有三个编码、商品名称前后不一致、有些订单缺字段……

解法:我们没有追求”一次性完美迁移”,而是做了三阶段迁移

  1. 先迁基础数据(门店、商品、会员),校验通过后切流量;
  2. 历史订单数据后台慢慢迁,迁完做对账;
  3. 实在对不上的老数据,保留查询入口但不参与新系统计算。

坑3:门店网络不稳定导致的数据延迟

有些商场门店的网络时好时坏,设备数据经常延迟几小时才上来,导致总部大屏上的数字”跳变”。

解法:我们在数据处理层加了水位线机制。对于延迟超过一定时间的数据,不更新实时大屏,只进历史库。同时给大屏加了一个”数据完整度”的指标,让看的人心里有数。

效果:从”拼数据”到”用数据”

项目上线3个月后,茶语的变化很明显:

  • 上新速度:以前上一款新品要改小程序、改ERP、改设备参数,至少一周;现在中台配置一下,半天搞定;
  • 运维效率:以前设备故障要等门店报,现在中台自动告警,平均故障响应时间从4小时降到了40分钟;
  • 数据决策:总部终于能看到实时的单店数据了,区域经理不用再天天发Excel报表。

复盘心得

做中台项目,最大的坑往往不是技术,而是**“为了中台而中台”**。我们见过不少企业,花了大价钱建中台,结果业务部门还是觉得不好用,因为中台团队和业务团队是脱节的。

这次项目能做成,一个很重要的原因是:我们没有先建一个”大而全”的中台,而是从最痛的业务场景切入,边建边用。先打通设备数据和订单数据,解决了”设备故障发现慢”和”数据对不上”这两个最痛的问题,让业务部门看到价值,然后再逐步扩展。

中台不是目的,解决业务问题才是。

Project Background: The “System Patchwork” of 200 Stores

TeaTalk is a tea beverage chain with 200+ stores. When they came to us, their IT landscape was a classic “patchwork”:

  • Store side: A third-party ordering mini program, but data lived with the vendor — changing a membership rule required a two-week wait in their queue.
  • Device side: Ice makers, water boilers, and smart tea barrels came from three different manufacturers, each with their own app. Store managers had 5 device management apps on their phones.
  • HQ side: ERP, finance, and HR systems all ran independently. Getting a “daily cups per store” report meant exporting data from three systems and stitching it together.

The boss’s request was straightforward: Can we manage all of this with one system?

This is a classic middle platform scenario. But a middle platform isn’t just buying a shelf and hanging things on it — the real challenge is “unification”: weaving heterogeneous systems, heterogeneous devices, and heterogeneous data into one cohesive system.

Core Challenges: Three “Differences”

Before starting, we mapped out the problems and summarized them as three “differences”:

1. Different Terminal Protocols

5 types of devices, 5 protocols: smart tea barrels use MQTT, ice makers use Modbus RTU, water boilers use proprietary HTTP APIs, POS machines use serial print data, and an old temperature control system uses custom TCP protocol.

If we wrote integration code for each device separately, that’s 5 sets of logic — and adding new devices means writing more. Maintenance costs explode.

2. Different Data Formats

Even for the same metric “temperature”:

  • Tea barrel reports: {device_id: "xxx", temp: 85.5, ts: 1655...}
  • Ice maker reports: ["IC-001", "TANK", -5.2, "2023-06-15 14:30:00"]

Field names, data types, time formats — all different.

3. Different Business Definitions

“Order count” in the store mini program wasn’t the same as “order count” in ERP — the mini program included canceled orders, ERP only counted completed ones. There were a dozen similar definition differences, which is why HQ reports never matched.

Middle Platform Architecture: Layered Decoupling

To address these three issues, our middle platform architecture uses a layered design:

┌─────────────────────────────────────────────────┐
│              Application Layer                   │
│  Store Mini Program / HQ Admin / Analytics       │
├─────────────────────────────────────────────────┤
│              Service Layer                       │
│  Order / Member / Device / Inventory Services    │
│  (Unified API Gateway + Unified Data Model)      │
├─────────────────────────────────────────────────┤
│              Access Layer                        │
│  Protocol Gateway / Message Queue / Data Cleaner │
│  MQTT / Modbus / HTTP / Custom TCP               │
├─────────────────────────────────────────────────┤
│              Data Layer                          │
│  Time-Series DB (device data) / Relational DB    │
└─────────────────────────────────────────────────┘

Three key design principles:

1. Access Layer: Protocol Conversion + Unified Message Format

We built a protocol adaptation gateway at the access layer. All device data comes in, gets converted to a unified JSON message format, then goes into the message queue.

For example, Modbus data from an ice maker comes in and gets converted to:

{
  "device_id": "IC-001",
  "metric": "tank_temp",
  "value": -5.2,
  "timestamp": 1686810600,
  "unit": "celsius"
}

This way, the device service upstairs only handles one data format. Adding new devices means adding an adapter at the access layer — no changes needed upstairs.

2. Service Layer: Domain Model + Unified Definitions

The service layer follows Domain-Driven Design (DDD), splitting business into core services: orders, members, devices, inventory. Each service has its own database but provides unified APIs externally.

The most critical part here is unifying data definitions. We spent a full week with TeaTalk’s operations, finance, and store operations teams redefining every core metric, creating a “data dictionary.” For example, “order count” was explicitly defined as “number of paid and non-refunded orders” — every system follows this definition.

3. Data Layer: Hot-Cold Separation

Device data and business data have completely different characteristics:

  • Device data: High volume (200 stores × 5 devices × every 30s = ~3M records/day), write-heavy, strongly time-series.
  • Business data: Lower volume (tens of thousands of orders/day), balanced read-write, complex relationships.

So we used hybrid storage: device data goes into a time-series database (TDengine), business data goes into a relational database (PostgreSQL). When joint analysis is needed, aggregation happens at the service layer rather than forcing everything into one database.

Pitfalls and Solutions

A few memorable pitfalls from the project:

Pitfall 1: Device Data Volume Far Exceeded Estimates

In the first week after launch, we found actual data volume was 3x the estimate — some devices reported every 5 seconds, not every 30 seconds. The time-series database write pressure spiked.

Solution: Added edge aggregation at the access layer. Edge gateways store fine-grained (5s) data locally, but report 1-minute aggregated data upstream. When detailed investigation is needed, we pull from the gateway locally. This reduced upstream volume by 12x.

Pitfall 2: Dirty Data in Legacy System Migration

When migrating historical data from the old ERP, we found massive dirty data: the same store had three codes, product names were inconsistent, some orders were missing fields…

Solution: We didn’t aim for “perfect one-time migration.” Instead, we did a three-phase migration:

  1. Migrate base data first (stores, products, members), validate, then cut traffic.
  2. Historical order data migrates slowly in the background, with reconciliation afterward.
  3. Old data that truly can’t be reconciled stays queryable but doesn’t participate in new system calculations.

Pitfall 3: Data Delays from Unstable Store Networks

Some mall stores had spotty networks, with device data often arriving hours late, causing “jumps” in HQ dashboard numbers.

Solution: Added a watermark mechanism in the data processing layer. Data delayed beyond a threshold doesn’t update the real-time dashboard — it only goes into the historical database. We also added a “data completeness” indicator to the dashboard so viewers have context.

Results: From “Stitching Data” to “Using Data”

Three months after launch, the changes at TeaTalk were clear:

  • New product speed: Previously, launching a new product meant changing the mini program, changing ERP, changing device parameters — at least a week. Now it’s configured in the middle platform and done in half a day.
  • Ops efficiency: Previously, equipment failures waited for store reports. Now the middle platform auto-alerts, and average failure response time dropped from 4 hours to 40 minutes.
  • Data-driven decisions: HQ can finally see real-time per-store data. Regional managers no longer send daily Excel reports.

Retrospective

The biggest pitfall in middle platform projects isn’t technology — it’s “building a middle platform for the sake of building a middle platform.” We’ve seen companies spend fortunes on middle platforms that business departments still find unusable, because the middle platform team is disconnected from the business teams.

A key reason this project succeeded: we didn’t start by building a “big and complete” middle platform. Instead, we started from the most painful business scenario, building and using simultaneously. We first unified device data and order data, solving the two most painful problems — “slow equipment failure detection” and “data that never matches” — letting the business see value, then gradually expanded.

The middle platform isn’t the goal. Solving business problems is.