Flink 內部是基于producer-consumer模型來進行消息傳遞的,Flink的反壓設計也是基于這個模型。
Flink 使用了高效有界的分布式阻塞隊列,就像 Java 通用的阻塞隊列(BlockingQueue)一樣。
下游消費者消費變慢,上游就會受到阻塞。
- Flink 1.5 之前的版本并沒有對反壓做特別的處理,它利用buffer來暫存堆積的無法處理的數據,當 buffer 用滿了,則上游的流阻塞,不再發送數據??梢姶藭r的反壓是從下游往上游傳播的,一直往上傳播到 Source Task 后,Source Task最終會降低或提升從外部Source 端讀取數據的速率。
這種機制有一個比較大的問題,在這樣的一個場景下:同一 Task的不同 SubTask 被安排到同一個 TaskManager,則SubTask與其他TaskManager 的網絡連接將被多路復用并共享一個 TCP信道以減少資源使用,所以某個 SubTask產生了反壓的話會把多路復用的TCP通道占住,從而會把其他復用同一 TCP信道的且沒有流量壓力的SubTask阻塞。
- Flink1.5版本之后的基于Credit反壓機制解決了上述問題。
這種機制主要是每次上游SubTask給下游SubTask發送數據時,會把Buffer中的數據和上游ResultSubPartition堆積的數據量Backlog size發給下游,下游會接收上游發來的數據,并向上游反饋目前下游現在的Credit值,Credit值表示目前下游可以接收上游的Buffer量,1個Buffer等價于1個Credit。
可見,這種策略上游向下游發送數據是按需發送的,而不是和之前一樣會在公用的Netty和TCP這一層數據堆積,避免了影響其他SubTask通信的問題。