数据交换协议:JDBC/ODBC、FTP/SFTP、Kafka、RESTful API、GraphQL
聊到数据交换,绕不开的就是协议。说白了,协议就是数据从一个系统跑到另一个系统时,大家约定好的「交通规则」。我做了这么多年数据架构,见过太多项目在协议选型上栽跟头——要么选错了工具,要么低估了场景复杂度。
今天咱们就把这五种主流协议掰开揉碎,看看它们各自擅长什么、不擅长什么。
JDBC/ODBC:数据库之间的直通车
JDBC(Java Database Connectivity)和 ODBC(Open Database Connectivity)是最传统的数据交换方式。它们的作用很简单:让应用程序直接连上数据库,执行 SQL,拿到结果。
适用场景:
- 数据量不大(百万级以内)的批量查询
- 需要实时读取数据库表的场景
- ETL 工具(如 Kettle、Informatica)的底层连接
核心特点:JDBC 是 Java 生态的标准,ODBC 是 Windows 生态的标准。现在大部分数据库都支持 JDBC,ODBC 用得少了。
我记得有一次做银行报表系统,需要从 Oracle 拉取前一天的交易数据。当时团队直接用 JDBC 写了个定时任务,每天凌晨跑一次。数据量大概 200 万行,跑了半年都没出问题。但后来业务扩张,数据量涨到 2000 万行,JDBC 直连就开始卡了——查询超时、连接池爆满,搞得运维天天半夜被叫醒。
避坑指南:我曾经见过一个项目,用 JDBC 直连去拉每天上亿条日志数据。结果数据库直接被拖垮,生产环境挂了两个小时。JDBC/ODBC 不是万能的,数据量大了一定要加中间层。
FTP/SFTP:文件传输的老黄牛
FTP(File Transfer Protocol)和 SFTP(SSH File Transfer Protocol)是文件级别的数据交换协议。FTP 明文传输,SFTP 加密传输。现在生产环境基本只用 SFTP。
适用场景:
- 批量文件交换(CSV、JSON、XML)
- 跨组织、跨网络的数据传输
- 非实时、定时调度的数据同步
| 特性 | FTP | SFTP |
|---|---|---|
| 加密 | 无(明文) | 有(SSH 加密) |
| 端口 | 21(控制)/20(数据) | 22 |
| 防火墙友好 | 差(需要动态端口) | 好(单端口) |
| 适用场景 | 内网、非敏感数据 | 外网、敏感数据 |
我个人习惯是:只要涉及跨网络传输,一律用 SFTP。别图省事用 FTP,万一数据被截获,背锅的是你。
举个例子,我之前做政府项目,需要和社保局交换参保数据。对方只支持 SFTP,每天凌晨三点推送一个压缩包过来。我们这边写个监听程序,文件一到就解压、校验、入库。这种模式稳定得很,跑了两年没出过岔子。
小技巧:SFTP 传输大文件时,建议先传 .tmp 后缀的临时文件,传完再重命名。这样能避免对方读到不完整的文件。
Kafka:流式数据的主动脉
Kafka 不是传统意义上的「协议」,它是一个分布式消息系统。但因为它定义了生产者-消费者之间的数据交换规范,所以咱们也把它归到协议里聊。
适用场景:
- 高吞吐、低延迟的实时数据流
- 日志采集、用户行为追踪
- 微服务之间的异步解耦
- 数据中台的实时数据管道
Kafka 的核心优势是「削峰填谷」。你想想看,双十一零点瞬间涌入几亿条订单数据,数据库根本扛不住。但用 Kafka 做缓冲,生产者只管往里面写,消费者按自己的节奏慢慢消费,系统就不会被冲垮。
关键概念:Topic(主题)、Partition(分区)、Consumer Group(消费组)。分区数是 Kafka 性能的关键,一般建议分区数不超过 Broker 数量的 10 倍。
我记得有个电商项目,需要实时同步订单数据到数据中台。最开始用 JDBC 直连,数据库压力太大。后来改成 Kafka,订单服务把数据发到 Topic,数据中台订阅消费,两边都轻松了。吞吐量从每秒几百条提升到几万条。
// 生产者示例(Java)
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
Producer<String, String> producer = new KafkaProducer<>(props);
producer.send(new ProducerRecord<>("order-topic", "order-12345", "{'orderId':12345,'amount':99.9}"));
producer.close();
避坑指南:我曾经遇到过 Kafka 消息丢失的问题。原因是生产者没有开启 acks=all,导致 Leader 挂了之后消息没同步到 Follower。生产环境一定要把 acks 设成 all,别为了那点性能牺牲可靠性。
RESTful API:系统间的通用语言
RESTful API 是基于 HTTP 协议的数据交换方式。它用 GET/POST/PUT/DELETE 对应 CRUD 操作,数据格式通常是 JSON 或 XML。
适用场景:
- 系统间的实时接口调用
- 微服务之间的同步通信
- 对外提供数据服务(Open API)
- 移动端和后端的数据交互
说白了,RESTful API 就是让两个系统像打电话一样,一问一答。你发个请求过去,对方立刻给你返回结果。这种模式简单直观,但缺点也很明显——如果对方响应慢,你就得一直等着。
| 方法 | 用途 | 幂等 |
|---|---|---|
| GET | 查询数据 | 是 |
| POST | 创建数据 | 否 |
| PUT | 全量更新 | 是 |
| PATCH | 部分更新 | 否 |
| DELETE | 删除数据 | 是 |
我个人习惯是:对外暴露的接口尽量用 RESTful,因为它的生态最成熟,各种语言都有现成的客户端。但内部系统之间,如果对性能要求高,我会考虑 gRPC 或者直接走消息队列。
小技巧:RESTful API 的响应一定要加分页、限流和超时控制。我曾经见过一个接口没做限流,被爬虫一刷直接打挂了,连带影响了十几个下游系统。
GraphQL:灵活查询的瑞士军刀
GraphQL 是 Facebook 推出的查询语言。它允许客户端精确指定需要哪些字段,服务端按需返回,不多不少。
适用场景:
- 前端需要灵活组合数据的场景
- 多端(Web、iOS、Android)共用一套接口
- 数据模型复杂、关联关系多的系统
你想想看,传统 RESTful API 返回的数据结构是固定的。前端要三个字段,后端可能返回十个。用 GraphQL,前端可以这样写:
query {
user(id: "12345") {
name
email
orders {
orderId
amount
}
}
}
后端只返回 name、email 和 orders 里的 orderId、amount,其他字段一概不返回。这样网络传输量小,前端也省了解析的功夫。
核心优势:一次请求拿到所有需要的数据,避免 RESTful 的「N+1 查询问题」。比如你要查一个用户和他的所有订单,RESTful 需要先调 /user/12345,再调 /user/12345/orders,而 GraphQL 一次搞定。
我记得有个项目是做移动端资讯 App,内容模型特别复杂——文章、评论、作者、标签、分类,各种关联。用 RESTful 写接口,前端调了七八次才拼出完整页面。后来改成 GraphQL,一次查询全搞定,页面加载速度提升了 40%。
避坑指南:GraphQL 的查询复杂度很难控制。我曾经见过前端写了个嵌套十层的查询,直接把数据库查挂了。一定要做查询深度限制和耗时限制,别让客户端为所欲为。
协议选型对比
说了这么多,到底怎么选?我整理了一张对比表,方便你快速决策:
| 协议 | 实时性 | 数据量 | 复杂度 | 典型场景 |
|---|---|---|---|---|
| JDBC/ODBC | 高 | 小-中 | 低 | 数据库直连查询 |
| FTP/SFTP | 低 | 大 | 低 | 批量文件交换 |
| Kafka | 高 | 极大 | 中 | 实时数据流 |
| RESTful API | 高 | 小 | 低 | 系统间实时调用 |
| GraphQL | 高 | 小 | 中-高 | 灵活查询、多端共用 |
选型的时候,记住一个原则:没有最好的协议,只有最合适的场景。数据量大、实时性要求不高,用 SFTP;需要高吞吐实时流,用 Kafka;系统间简单调用,用 RESTful;前端需要灵活查询,用 GraphQL。
协议选型决策流程
下面这张图是我自己总结的选型流程,帮你快速定位该用哪种协议:
嗯,这张图基本覆盖了日常工作中 90% 的选型场景。你只要顺着流程走一遍,基本不会选错。
最后说一句:协议选型不是一锤子买卖。系统在发展,数据量在增长,需求在变化。我建议你每半年复盘一次当前的协议选型,看看是否需要调整。别等到系统扛不住了才想起来改,那时候代价就大了。