之前的文章中提過,structured streaming處理流數據,如果使用聚合,將會有window的概念,對應屬性watermark.不知你是否了解過druid,druid處理數據同樣有窗口期的概念,用于判斷數據何時丟棄.超時的數據將被直接丟棄.
druid的實現比較完善.不管是窗口期的內存數據還是固化到hdfa中的數據,都可以實時聯合查詢.而structured streaming目前尚未見到類似實現.前文提到它支持三種輸出模式.complete.append和update.對于支持update的sink類型還好.若使用的sink類型,如elastatic search,不支持update呢?
試想一下,如果你的流數據每分鐘聚合一次.允許延遲十分鐘到達的數據有效.那么,對于僅支持append格式的es來說,從es查詢到的數據將一直延遲十分鐘.因為窗口期的數據存在發生變化的可能性.所以直到數據有效期結束才會被寫入es.這樣的查詢延時當然難以被接受.
對于該問題,或許可以期待structured后續版本更新完善.現階段,如果使用es等僅支持append模式的sink,
方案一:
可以考慮使用上文提到的foreach模式,首先將數據以update寫入redis等內存數據庫.再通過控制redis的數據過期來觸發es寫入.該方式的實現有可行性.略微復雜.需要自己寫邏輯控制數據的過期和同步.查詢的時候需要聯合es進行查詢.
方案二:
也可以考慮兩個sink同時使用.一方面實時寫入redis.且redis數據過期時間為十分鐘.另一方面寫入es.查詢時聯合兩者查詢.這種方式的缺陷是數據會被消費和處理兩遍.增加資源消耗.
方案三:使用foreach update直接寫入es.而不直接使用es官方提供的api.這種方式的缺點是增加es寫入負擔和硬盤資源消耗.同時.會有大量冗余數據進入es.查詢時需做過濾.
方案四:
更直接的.如果可以.換掉es吧.使用kudu等列式存儲.像上文所寫存儲redis的方式將數據寫入kudu.該方式簡單易行.需要關注的就是kudu的update性能.