2. 数据源接入:关系型数据库、NoSQL数据库与API接口

好,咱们直接进入正题。数据源接入这块,说白了就是解决「数据从哪来」的问题。我做了这么多年大屏项目,发现很多团队前期把精力都花在可视化效果上,结果数据接不进来,或者接进来全是脏数据,那才叫一个尴尬。

今天咱们就聊聊三种最主流的数据源接入方式:关系型数据库、NoSQL数据库,还有API接口。每种我都会结合自己的踩坑经历来讲。

2.1 关系型数据库接入(MySQL / PostgreSQL)

关系型数据库,至今仍是企业数据的主力军。MySQL和PostgreSQL,我两边都用过,各有千秋。

MySQL接入要点

我个人习惯用JDBC直连的方式。但要注意,大屏监控对实时性要求高,你不能像做报表那样一次性拉全量数据。

// 伪代码示例:MySQL增量拉取
String sql = "SELECT * FROM orders WHERE update_time > ?";
// 每次记录上次拉取的时间戳
preparedStatement.setTimestamp(1, lastFetchTime);

这里有个坑——时间戳精度问题。我曾经遇到过MySQL的datetime精度只到秒,同一秒内更新的数据会被漏掉。后来我改用bigint存储毫秒时间戳,问题才解决。

避坑指南:MySQL的默认事务隔离级别是「可重复读」,如果你用主从复制,从库可能会有延迟。我建议对实时性要求高的场景,直接读主库,或者用半同步复制。

PostgreSQL接入优势

PostgreSQL有个特性我很喜欢——逻辑复制。它可以直接把数据库的变更推送给消费者,不需要你写轮询SQL。

-- PostgreSQL 发布订阅示例
CREATE PUBLICATION monitor_pub FOR TABLE orders, users;
-- 订阅端自动接收变更

你想想看,这样是不是省了很多事?我在一个金融项目中就用这个方案,延迟控制在100毫秒以内。

对比项 MySQL PostgreSQL
增量拉取方式 时间戳/自增ID轮询 逻辑复制/WAL日志
典型延迟 1-5秒(轮询间隔) 50-200毫秒
适合场景 中小规模、简单查询 高实时、复杂分析

2.2 NoSQL数据库接入(MongoDB / Redis)

NoSQL这边,MongoDB和Redis是两大主力。它们的数据模型和关系型完全不同,接入方式也得跟着变。

MongoDB:Change Streams 是真香

MongoDB 3.6之后推出了Change Streams,这玩意儿简直就是为大屏监控量身定做的。它让你能实时监听集合的增删改操作。

// MongoDB Change Streams 示例
MongoCollection<Document> collection = database.getCollection("orders");
ChangeStreamIterable<Document> changeStream = collection.watch();
changeStream.forEach(event -> {
    // event里有操作类型、变更前后的数据
    System.out.println(event.getFullDocument());
});

我在一个电商大屏项目里就用这个方案。用户下单后,数据几乎零延迟地出现在大屏上。嗯,这里要注意:Change Streams依赖副本集,单节点MongoDB用不了。

小技巧:如果数据量特别大,可以在Change Streams上加$match管道,只监听你关心的操作类型,比如只监听insert和update,忽略delete。

Redis:订阅发布模式

Redis做数据源接入,最常见的场景是缓存和消息队列。我个人推荐用Pub/Sub模式,而不是轮询Redis的key。

// Redis 订阅示例
Jedis jedis = new Jedis("localhost");
jedis.subscribe(new JedisPubSub() {
    public void onMessage(String channel, String message) {
        // 直接拿到实时消息
        System.out.println("收到数据:" + message);
    }
}, "monitor_channel");

为什么不用轮询?你想想看,如果每秒轮询一次,1000个key就是1000次网络开销。而Pub/Sub是推模式,数据到了才触发,性能好得多。

不过要提醒一句:Redis的Pub/Sub是即发即忘的。如果消费者挂了,消息就丢了。我在一个项目中就吃过这个亏,后来改用Redis Stream才解决。

2.3 API接口数据接入

API接入,说白了就是调用别人的HTTP接口拿数据。这看起来简单,但坑最多。

RESTful API vs WebSocket

这两种方式,我一般这样选:

  • RESTful API:适合低频数据,比如每小时拉一次报表数据
  • WebSocket:适合高频实时数据,比如股票行情、设备状态

举个例子,我之前做的一个物联网大屏项目,设备状态每秒都在变。如果用RESTful API轮询,每秒请求一次,服务器压力大不说,数据还有延迟。后来改成WebSocket,设备主动推送,服务器轻松多了。

// WebSocket 客户端示例(Java)
@ClientEndpoint
public class DataClient {
    @OnMessage
    public void onMessage(String message) {
        // 实时接收数据
        JSONObject data = JSON.parseObject(message);
        updateScreen(data);
    }
}
核心原则:API接入一定要做「熔断降级」。我曾经遇到第三方API突然超时,结果整个大屏卡死了。后来加了Hystrix熔断,超时3秒就返回缓存数据,大屏至少还能看。

API接入的通用注意事项

不管用哪种协议,这几个点一定要记住:

  1. 限流:别把别人的API打挂了,一般接口都有QPS限制
  2. 重试机制:网络抖动是常态,指数退避重试是标配
  3. 数据校验:API返回的数据格式可能变,一定要做字段校验
  4. 日志记录:每次请求的耗时、状态码都要记下来,方便排查问题

我记得有一次,第三方API突然把返回字段从"user_name"改成了"username",我们没做校验,结果大屏上用户名字段全空了。从那以后,我每个API接入都加了一层数据转换适配器。

小结

数据源接入这块,没有银弹。关系型数据库稳定可靠,NoSQL灵活高效,API接口通用性强。关键是根据你的业务场景选对方案。

我个人建议:先搞清楚数据的实时性要求。秒级延迟用轮询或Change Streams,毫秒级延迟用WebSocket或逻辑复制。别一上来就追求最炫的技术,稳定才是第一位的。

下一章咱们聊聊数据清洗和转换,那又是另一番天地了。