4. 临床数据采集与接入工程
临床数据采集与接入是专题数据集市的第一道工程关口。它要解决的核心问题不是“能不能把数据搬过来”,而是“搬过来的数据是否完整、及时、可追溯、可重放”。在真实医院环境中,数据源往往同时包含 HIS 业务库、LIS 检验系统、PACS 影像报告、电子病历文书、护理记录、设备监护流以及第三方上传文件。不同来源的更新频率、数据量级、接口能力和合规约束差异极大,因此接入层必须按数据特征选择批量抽取、增量捕获、接口对接、文件导入或实时流接入中的一种或多种组合,而不是用单一通道硬套所有场景。
五类接入通道的适用边界
批量抽取适合历史数据初始化、T+1 全量对账和低频维表同步。典型做法是通过 JDBC 或数据库导出工具,在业务低峰期按分区或按时间窗口拉取,例如每晚 01:00 抽取前一日出院病案首页。它的优点是实现简单、对源库压力可控;缺点是时效性差,且必须解决“抽取过程中源数据仍在变化”导致的一致性缺口。
增量捕获适合高价值业务表的准实时同步。常见实现包括基于时间戳/自增序列的轮询增量、基于数据库日志的 CDC(如 MySQL binlog、Oracle LogMiner、PostgreSQL 逻辑复制)。时间戳增量实现成本低,但要求源表有可靠且单调的更新时间字段,且无法捕获物理删除;日志级 CDC 能捕获插入、更新、删除,但需要额外权限、日志保留窗口和位点管理。工程上必须记录“上次成功位点”,并支持断点续传与重复消费幂等。
接口对接适合跨机构、跨系统或受控访问场景,例如通过 HL7 v2 消息、FHIR RESTful API、WebService 获取患者、就诊、检验结果。接口对接的关键不在调用本身,而在于约定分页、限流、重试、鉴权和错误码语义。例如 FHIR 接口常用 _count 与 _offset 分页,遇到 429 应退避重试,遇到 401 应刷新令牌而不是无限重试。
文件导入适合批量补录、外部机构交付和无法直连的系统。CSV、Excel、XML、JSON、DICOM 文件都可能出现。文件导入必须做“落地—校验—入库”三段式处理:先原样归档,再解析校验,最后写入贴源层,避免解析失败后原始文件丢失。
实时流接入适合监护设备、急诊看板、手术麻醉等对延迟敏感的场景。通常通过 Kafka、MQTT 或 WebSocket 接收消息,按患者标识和事件时间做窗口聚合。实时流接入必须处理乱序、重复和迟到数据,常用事件时间加水印机制,并保留原始消息以便回放。
增量捕获的位点管理与幂等设计
增量捕获最容易出问题的不是“怎么读日志”,而是“位点怎么存、失败怎么恢复”。以 MySQL binlog 为例,接入任务需要维护 binlog_file 与 binlog_position 两个位点,并在目标贴源层写入成功后,才把位点提交到元数据库。若先提交位点再写目标,一旦写入失败就会丢数据;若先写目标再提交位点,重复消费时可能产生重复记录,因此目标表必须按业务主键做幂等写入,例如使用 INSERT ... ON DUPLICATE KEY UPDATE 或先删后插的批次覆盖策略。
对于基于时间戳的轮询增量,需要额外处理“同一时间戳多条记录”和“源库时间回拨”两个边界。常见做法是采用 (update_time, id) 组合游标,查询条件写成 update_time > :last_time OR (update_time = :last_time AND id > :last_id),并按 update_time, id 排序分页。这样即使同一秒内有多条更新,也不会漏读或重复。
接口对接与文件导入的工程细节
接口对接要区分“拉”和“推”。拉取型接口需要处理分页、限流和增量水位;推送型接口需要提供接收端点、验签、去重和落库确认。以 FHIR 患者查询为例,一次典型请求可写为:
GET /fhir/Patient?_lastUpdated=gt2024-06-01T00:00:00Z&_count=100&_offset=0
Headers:
Authorization: Bearer <token>
Accept: application/fhir+json
返回结果中若 total 大于当前页数量,应继续翻页直到取完;若返回 429,则按指数退避等待 1s、2s、4s 后重试,并记录重试次数。所有接口响应都应保留原始报文摘要和业务主键,便于后续对账。
文件导入的关键是“先归档、再解析、后入库”。例如一批外部检验 CSV 文件到达后,先按 来源系统/日期/文件名 归档到原始区,再逐行解析。解析时至少校验:文件行数是否与清单一致、必填列是否为空、患者标识能否映射、检验项目编码是否在字典表中。若某行校验失败,不应整批丢弃,而应写入错误表并标记行号,允许修正后重跑该批次。
实时流接入的乱序与迟到处理
监护设备流通常带有设备时间戳,但网络传输会导致到达顺序与事件顺序不一致。工程上应以事件时间作为窗口划分依据,并设置水印容忍迟到。例如设定水印延迟为 30 秒,则窗口 [10:00:00, 10:01:00) 在收到 10:01:30 之后的水印时才触发计算。对于超过水印的迟到数据,可写入侧输出流单独处理,而不是直接丢弃。同时,每条消息应携带 device_id + measure_time + metric_code 作为去重键,防止网络重传造成重复计数。
质量控制与对账闭环
接入质量不能只看“任务是否跑成功”,而要看数据是否可信。建议在每个通道落地后执行四类检查:第一,完整性检查,比对源端记录数与目标端记录数,偏差超过阈值即告警;第二,主键唯一性检查,确认贴源层无重复主键;第三,时间戳合理性检查,识别未来时间、过早时间和空时间;第四,编码映射检查,统计未匹配字典的编码占比。对于批量抽取,还应按批次生成对账文件,记录批次号、抽取起止时间、源端行数、目标端行数、失败行数和重试次数,作为后续审计和问题定位的依据。
综合来看,批量抽取、增量捕获、接口对接、文件导入和实时流接入并不是互斥选项,而是按数据时效、数据量、源系统能力和合规要求组合使用的工具箱。工程实现的重点在于:为每条通道定义清晰的位点或批次标识,为每次写入设计幂等策略,为每类异常保留可重放的原始数据,并为每个批次建立可对账的质量指标。只有这样,贴源层才能真正成为专题数据集市可信、可追溯、可恢复的数据底座。