小紅希望小明多讀書,常尋找好書給小明看,之前的方式是這樣:小紅問小明什麼時候有空,把書給小明送去,並親眼監督小明讀完書才走。久而久之,兩人都覺得麻煩。
後來的方式改成了:小紅對小明說「我放到書架上的書你都要看」,然後小紅每次發現不錯的書都放到書架上,小明則看到書架上有書就拿下來看。
書架就是一個訊息佇列,小紅是生產者,小明是消費者。
這帶來的好處有:
1.小紅想給小明書的時候,不必問小明什麼時候有空,親手把書交給他了,小紅只把書放到書架上就行了。這樣小紅小明的時間都更自由。
2.小紅相信小明的讀書自覺和讀書能力,不必親眼觀察小明的讀書過程,小紅只要做一個放書的動作,很節省時間。
3.當明天有另一個愛讀書的小夥伴小強加入,小紅仍舊只需要把書放到書架上,小明和小強從書架上取書即可(唔,姑且設定成多個人取一本書可以每人取走一本吧,可能是拷貝電子書或影印,暫不考慮版權問題)。
4.書架上的書放在那裡,小明閱讀速度快就早點看完,閱讀速度慢就晚點看完,沒關係,比起小紅把書遞給小明並監督小明讀完的方式,小明的壓力會小一些。
這就是訊息佇列的四大好處:
1.解耦
每個成員不必受其他成員影響,可以更獨立自主,只通過一個簡單的容器來聯絡。
小紅甚至可以不知道從書架上取書的是誰,小明也可以不知道往書架上放書的人是誰,在他們眼裡,都只有書架,沒有對方。
毫無疑問,與一個簡單的容器打交道,比與複雜的人打交道容易一萬倍,小紅小明可以自由自在地追求各自的人生。
2.提速
小紅選擇相信「把書放到書架上,別的我不問」,為自己節省了大量時間。
小紅很忙,只能抽出五分鐘時間,但這時間足夠把書放到書架上了。
3.廣播
小紅只需要勞動一次,就可以讓多個小夥伴有書可讀,這大大地節省了她的時間,也讓新的小夥伴的加入成本很低。
4.削峰
假設小明讀書很慢,如果採用小紅每給一本書都監督小明讀完的方式,小明有壓力,小紅也不耐煩。
反正小紅給書的頻率也不穩定,如果今明兩天連給了五本,之後隔三個月才又給一本,那小明只要在三個月內從書架上陸續取走五本書讀完就行了,壓力就不那麼大了。
當然,使用訊息佇列也有其成本:
1.引入複雜度
毫無疑問,「書架」這東西是多出來的,需要地方放它,還需要防盜。2.暫時的不一致性假如媽媽問小紅「小明最近讀了什麼書」,在以前的方式裡,小紅因為親眼監督小明讀完書了,可以底氣十足地告訴媽媽,但新的方式裡,小紅回答媽媽之後會心想「小明應該會很快看完吧……」
這中間存在著一段「媽媽認為小明看了某書,而小明其實還沒看」的時期,當然,小明最終的閱讀狀態與媽媽的認知會是一致的,這就是所謂的「最終一致性」。
那麼,該使用訊息佇列的情況需要滿足什麼條件呢?
1.生產者不需要從消費者處獲得反饋
引入訊息佇列之前的直接呼叫,其介面的返回值應該為空,這才讓明明下層的動作還沒做,上層卻當成動作做完了繼續往後走——即所謂非同步——成為了可能。
小紅放完書之後小明到底看了沒有,小紅根本不問,她預設他是看了,否則就只能用原來的方法監督到看完了。
2.容許短暫的不一致性
媽媽可能會發現「有時候據說小明看了某書,但事實上他還沒看」,只要媽媽滿意於「反正他最後看了就行」,非同步處理就沒問題。
如果媽媽對這情況不能容忍,對小紅大發雷霆,小紅也就不敢用書架方式了。
3.確實是用了有效果即解耦、提速、廣播、削峰這些方面的收益,超過放置書架、監控書架這些成本。
否則如果是盲目照搬,「聽說老趙家買了書架,我們們家也買一個」,買回來卻沒什麼用,只是讓步驟變多了,還不如直接把書遞給對方呢,那就不對了。
來自 zhuanlan.zhihu.com/p/24860107