实时计算相关问题及解决方案

1. 怎么处理 Spark structured streaming 慢速变化数据 join 的问题?

问题:从 MySQL 的一个表里面提取 metadata 然后和 structured streaming 的实时数据做 join,得到想要的结果。而mysql的表的数据有时候会变更,有没有办法让 structured streaming 隔一段时间(比如一天)去自动重新读一次 MySQL?

解决方案

  1. 不cache从MySQL读出来的DataFrame就可以了,这样每次查询都会重读一次 MySQL 表。
  2. 如果不接受不做cache对性能的负面影响,可以在另一个线程里 (StreamingQueryListener)unpersist再cache,每隔一段时间 unpersist一次MySQL的DataFrame再重新cache。

2. kafka不稳定导致Spark Streaming不稳定

问题:Spark Streaming每个批次Job都会通过DirectKafkaInputStream的comput方法获取消费的Kafka Topic当前最新的offset,如果此时kafka集群由于某些原因不稳定,就会导致 java.lang.RuntimeException: No leader found for partition xx的问题,由于此段代码运行在Driver端,如果没有做任何配置和处理的情况下,会导致程序直接挂掉。

解决方案
配置spark.streaming.kafka.maxRetries大于1,并且可以通过配置refresh.leader.backoff.ms参数设置每次重试的间隔时间。

3. Flume当中出现了流量瓶颈

问题:Flume是Kafka的前端,是所有数据进入Kafka的一个源头。我们在实践过程中发现,在Flume当中出现了流量瓶颈,更准确来说,是Flume的前一级服务器出现了数据堆积。结果发现数据通过连接Source的性能出现了瓶颈。

解决方案
一旦Flume出现堆积,首先要判断的就是数据堆积到底是出现在Flume的前面还是后面。后来我发现了一个很简单的判断方式,Channel其实是个简单的共享内存。如果数据的堆积是出现在后面Sink一端的话,那么当数据被源源不断地写到Channel里面,Sink又没法消费掉的时候,那么Channel应该就会满。所以,只要检查一下Channel中有没有满的报错,就能够分析出数据的瓶颈到底是出现在Flume的前面还是后面。经过检查之后,发现数据的堆积是在Flume的前面。
接下来,第一种方法,可以将数据拆分成多份,进行传输。此方法在当前项目中是不现实的。那么就采取第二种方法,可以先把它落盘,把它解到硬盘里面,只要IO性能能够勉强扛得住,通过一路分成多路,就可以通过多线程并发的方式来解决这个问题。在流计算当中,透传的性能不见得比落盘的性能要来得高,在实践过程中,只要IO性能扛得住,有时候可以改用落盘的方式,通过多线程来换取性能的提升。

4. Kafka的流量问题

问题:当Kafka出现新瓶颈时,是没有任何告警、日志可以看的,只能是最终数据中,数据的准确性出现问题了,数据量少了,或者如果在统计流量,就只会看到流量出现大幅度减少这个现象。同样,很多截然不同的原因导致的问题在流计算当中出现的结果都一样,都是数据量少了,结果不准确了。

解决方案
在项目中,最后发现问题出在网卡上。因为当时我们配置的是四块网卡,两主两备的方式,也就是说4块网卡中只有2块是有流量的,整个带宽是200MB左右。当出现数据堆积的时候,发现网络端口的send流量大约为190MB/s左右,几乎是2块千兆网卡的吞吐量,即网卡已经跑满了。因此,既然四块网卡是两主两备,那我就改成“四网卡”模式。最终发现,当流量超过300MB/s,Kafka节点的CPU和IO的使用率仍然不算高,因此可以大胆假设,如果用1块万兆网卡来替代现在的4块千兆网卡,每个Kafka节点的性能有望进一步提升,这样实际上还有望减少Kafka节点的数量。Kafka的网络传输坑至此解决。

猜你喜欢

转载自blog.csdn.net/weixin_42526352/article/details/105965342