我堅決反對,通過緩存傳遞數據!
朋友說他有一個巧妙架構方案,服務之間通過緩存傳遞數據:
如上圖:
- service-A將數據放入cache;
- service-B從cache里讀取數據;
朋友問我,這種架構設計好還是不好?
我旗幟鮮明的反對“服務之間通過緩存傳遞數據”,下面三種場景,這種設計都不適合。
場景一:數據管道場景,MQ比cache更加適合。
如果只是單純的將cache作為兩個服務數據通訊的管道,service-A生產數據,service-B(當然,可能有service-C/service-D等)訂閱數據,MQ比cache更加合適:
- MQ是互聯網常見的邏輯解耦,物理解耦組件,支持1對1,1對多各種模式,非常成熟的數據通道;
- 而cache反而會將service-A/B/C/D耦合在一起,大家要彼此協同約定key的格式,ip地址等;
- MQ能夠支持push,而cache只能拉取,不實時,有時延;
- MQ能支持數據落地,cache具備將數據存在內存里,具有“易失”性,當然,有些cache支持落地,但互聯網技術選型的原則是,讓專業的軟件干專業的事情:nginx做反向代理,db做固化,cache做緩存,mq做通道;
綜上,數據管道場景,MQ比cache更加適合。
場景二:數據共管場景,兩個(多個)service同時讀寫一個cache實例會導致耦合。
如果不是數據管道,是兩個(多個)service對一個cache進行數據共管,同時讀寫,也是不推薦的,這些service會因為這個cache耦合在一起:
- 大家要彼此協同約定key的格式,ip地址等,耦合;
- 約定好同一個key,可能會產生數據覆蓋,導致數據不一致;
- 不同服務業務模式,數據量,并發量不一樣,會因為一個cache相互影響;
例如:
service-A數據量大,占用了cache的絕大部分內存,會導致service-B的熱數據全部被擠出cache,導致cache失效。
又例如:
service-A并發量高,占用了cache的絕大部分連接,會導致service-B拿不到cache的連接,從而服務異常。
綜上,數據共管場景,多個service耦合在一個cache實例里,也是不推薦的,需要垂直拆分,實例解耦。
場景三:數據訪問場景,兩個(多個)service有讀寫一份數據的需求。
根據服務化的原則,數據是私有的(本質也是解耦):
- service層會向數據的需求方屏蔽下層存儲引擎,分庫,chace的復雜性;
- 任何需求方不能繞過service讀寫其后端的數據;
假設有其他service要有數據獲取的需求,應該通過service提供的RPC接口來訪問,而不是直接讀寫后端的數據,無論是cache還是db。
簡單總結
不管哪種場景,服務之間都不要使用緩存來傳遞數據:
- 數據管道場景:MQ比cache更合適;
- 數據共管場景:多個服務不應該共用一個cache實例,應該垂直拆分解耦;
- 數據訪問場景:服務化架構,不應該繞過service讀取其后端的cache/db,而應該通過RPC接口訪問;
知其然,知其所以然。
思路比結論更重要。