Redis - Reliable queue pattern

系統中如果有使用到 Redis,有時會碰到要將 Redis 內資料落地的情境。這時可能會用 Redis 的 List 做一個簡單的 Queue,將資料以先進先出的方式處理。


這樣的做法看似運作良好,但隱藏著一個潛在的問題。如果今天從 Redid 取出資料還未處理就發生錯誤,可能是機器當機重啟那種錯誤,就會有丟失資料的現象發生。


為了解決這樣的問題,可以套用 Reliable queue pattern,當資料確實被處理完才從 Redis 內移除。


簡單的說就是把資料的 Id 放在 List 之類的結構,實際的資料放在 Value,當你 Deque 時將 Id 從 Pendding 放到 Working,處理完才從 Working 清掉,順帶將 Value 對應的資料刪掉。


實作上通常 Pending 與 Working 會用 List 結構去實作,Value 會用 Hash 結構。


當資料要從 Redis 取出處理時,會先查看 Working 是否已經有資料,如果 Working 已經有資料,可能代表之前處理到一半之類的,這時資料直接由 Working 反查 Value 後吐回。如果 Working 沒資料,會從 Pending 將需要處理的 Id 透過 rpoplpush 命令轉到 Working,然後反查 Value 吐回。


資料處理完要將資料從 Redis 移除時,會將 Working 與 Value 中對應的資料移除。


需注意到套用 Reliable queue pattern 時,可能會依情境、需求、產品特性可能會有不同的變體,使用的資料結構也可視需要調動。


像是如果資料處理失敗達一定次數,可考慮是否從 Working 轉到 Fail,避免處理一直卡住。


若是考慮到 Sharding 的話,Working 需要 by Worker 散開,且還需要有當 worker 死掉的接手機制。