架構設計:生產者/消費者模式[1]:如何確定資料單元?

無痕幽雨發表於2018-02-09

架構設計:生產者/消費者模式[1]:如何確定資料單元?

文章目錄
★啥是資料單元?
★資料單元的特性
  既然前一個帖子已經搞過掃盲了,那接下來應該開始聊一些具體的程式設計技術問題了。不過在進入具體的技術細節之前,我們們先要搞明白一個問題:如何確定資料單元?只有把資料單元分析清楚,後面的技術設計才好搞。

★啥是資料單元?


  何謂資料單元捏?簡單地說,每次生產者放到緩衝區的,就是一個資料單元;每次消費者從緩衝區取出的,也是一個資料單元。對於前一個帖子中寄信的例子,我們可以把每一封單獨的信件看成是一個資料單元。
  不過光這麼介紹,太過於簡單,無助於大夥兒分析出這玩意兒。所以,後面我們們來看一下資料單元需要具備哪些特性。搞明白這些特性之後,就容易從複雜的業務邏輯中分析出適合做資料單元的東西了。

★資料單元的特性


  分析資料單元,需要考慮如下幾個方面的特性:

◇關聯到業務物件


  首先,資料單元必須關聯到某種業務物件。在考慮該問題的時候,你必須深刻理解當前這個生產者/消費者模式所對應的【業務邏輯】,才能夠作出合適的判斷。
  由於“寄信”這個業務邏輯比較簡單,所以大夥兒很容易就可以判斷出資料單元是啥。但現實生活中,往往沒這麼樂觀。大多數業務邏輯都比較複雜,當中包含的業務物件是層次繁多、型別各異。在這種情況下,就不易作出決策了。
  雖說這一步有難度,但是很重要!如果選錯了業務物件,會導致後續程式設計和編碼實現的複雜度大為上升,增加了開發和維護成本。

◇完整性


  所謂完整性,就是在傳輸過程中,要保證該資料單元的完整。要麼【整個】資料單元被傳遞到消費者,要麼完全沒有傳遞到消費者。不允許出現【部分】傳遞的情形。
  對於寄信來說,你【不能】把半封信放入郵筒;同樣的,郵遞員從郵筒中拿信,也【不能】只拿出信的一部分。

◇獨立性


  所謂獨立性,就是各個資料單元之間沒有互相依賴,某個資料單元傳輸失敗【不應該】影響已經完成傳輸的單元;也【不能】影響尚未傳輸的單元。
  為啥會出現傳輸失敗捏?假如生產者的生產速度在一段時間內一直超過消費者的處理速度,那就會導致緩衝區不斷增長並達到上限,之後就很不妙了(有些資料單元會被無情地拋棄)。如果資料單元相互獨立,等到生產者的速度降下來之後,後續的資料單元繼續處理,不會受到牽連;反之,如果資料單元之間有某種耦合,導致被丟棄的資料單元會影響到後續其它單元的處理,那就會使程式邏輯變得非常複雜。
  對於寄信來說,某封信弄丟了,不會影響後續信件的送達;當然更不會影響已經送達的信件。

◇顆粒度


  前面提到,資料單元需要關聯到某種業務物件。那麼資料單元和業務物件是否要一一對應捏?很多場合確實是一一對應的。
  不過,有時出於效能等因素的考慮,也可能會把N個業務物件打包成一個資料單元。那麼,這個N該如何取值就是顆粒度的考慮了。顆粒度的大小是有講究的。太大的顆粒度可能會浪費空間;太小的顆粒度可能會影響時間效能。顆粒度的權衡要基於多方面的因素,以及一些經驗值的考量。
  還是拿寄信的例子。如果顆粒度過小(比如設定為1),那郵遞員每次只取出1封信。如果信件多了,那就得來回跑好多趟,浪費了時間。
  如果顆粒度太大(比如設定為100),那寄信的人得等到湊滿100封信才拿去放入郵筒。假如平時很少寫信,就得等上很久,也不太爽。
  可能有同學會問:生產者和消費者的顆粒度能否設定成不同大小(比如對於寄信人設定成1,對於郵遞員設定成100)。當然,理論上可以這麼幹,但是在某些情況下會增加程式邏輯和程式碼實現的複雜度。後面討論具體技術時,大夥兒應該能體會到資料單元的重要性。

  好,資料單元的話題就說到這。希望通過本帖子,大夥兒能夠搞明白資料單元到底是怎麼一回事。下一個帖子,我們們來聊一下“基於佇列的緩衝區”,技術上如何實現。

回到本系列的目錄
版權宣告
本部落格所有的原創文章,作者皆保留版權。轉載必須包含本宣告,保持本文完整,並以超連結形式註明作者程式設計隨想和本文原始地址:
https://program-think.blogspot.com/2009/03/producer-consumer-pattern-1-data.html

相關文章