在 Spark 2.3 中,流与流的 Join(Stream-stream join)被正式支持。这样的 Join 难点就在于,在任意一个时刻,流数据都不是完整的,流 A 中后面还没到的数据有可能要和流 B 中已经有的数据 Join 起来再输出。为了解决这个问题,我们就要引入数据水印(Watermark)的概念。

数据水印定义了我们可以对数据延迟的最大容忍限度。

比如说,如果定义水印是 10 分钟,数据 A 的事件时间是 1:00,数据 B 的事件时间是 1:10,由于数据传输发生了延迟,我们在 1:15 才收到了 A 和 B,那么我们将只处理数据 B 并更新结果,A 会被无视。在 Join 操作中,好好利用水印,我们就知道什么时候可以不用再考虑旧数据,什么时候必须把旧数据保留在内存中。不然,我们就必须把所有旧数据一直存在内存里,导致数据不断增大,最终可能会内存泄漏。