系統設計典型問題的思考

y37f 9年前發布 | 14K 次閱讀 系統設計

這里總結典型的思路和題目。

首先,反復溝通和澄清系統需求。只有把需求澄清清楚了,才可以開始思考并落到紙面上。但是需求的溝通應該是持續和循序漸進的,問題很難從一開始就思考全面。最重要的條目包括:

  • use cases,通常問題只需要2~3個use cases需要考慮,其他的部分會晚些考慮,或者不考慮。這樣就可以簡化問題。
  • 用戶數量(用戶可以是下游系統或者人)、數據數量,澄清這個事實無疑非常重要,對系統設計的決策有重大意義。
  • 請求模型,比如讀遠大于寫,比如60%的請求都訪問top 20的記錄。
  • </ul>

    其次,嘗試抽象一個簡單的模型,從簡單模型開始,思考不同的場景和約束,逐步完善。落實到代碼上的時候,最核心的部分包括:

    • 模型的定義。
    • 代碼接口,API。
    • 數據是怎樣被存儲的,比如表結構和文件結構。
    • </ul>

      在此基礎上,考慮最基礎的組件和架構劃分,整個系統要分幾層,有哪些組件,各自什么作用,可能的瓶頸是什么等等。還有前面的API、模型分別被安插到哪部分上面,同時反復比較第一步的幾個use case是否都被滿足。

      再次,細化層結構和組件,比如:

      • 存儲層。是否需要持久化存儲?選擇文件、關系數據庫,還是NoSQL數據庫?
      • </ul>

        • 如果選擇關系數據庫,是否需要sharding或partition?參考Quora:What’s the difference between sharding and partition?
        • 如果選擇NoSQL數據庫,CAP中分別犧牲和優先保證哪一個?參考:Visual Guide to NoSQL System。擴容的策略(比如一致性hash)?
        • 存儲是否需要分層(比如冷層——文件、暖層——關系型數據庫、熱層——緩存,不同成本的存儲介質,用以應付不同的數據訪問頻率)?
        • </ul>

        • 集群。所有節點對等還是中心節點主備?請求負載分擔的策略?如何增減節點?如何判定節點健康狀況?是否需要會話?會話如何同步?Scale up和Scale out的區別,參考Wikipedia:Scalability
        • 消息模型。生產者和消費者的速率?無法應付時是否需要緩沖隊列?消息流量控制?速率控制的精細度?
        • 緩存系統。緩存的分層?分布式部署還是集中式緩存服務?使用什么緩存淘汰算法(比如LRU)?參考:In-Process Caching vs. Distributed Caching
        • 其中,系統瓶頸的識別和scale是緊密聯系著的兩個話題。在需求驅使的基礎上著手優化,比如緩存的應用,這需要建立在系統瓶頸被識別或者假定被識別的基礎上,否則就是亂槍打鳥。在瓶頸解決之后再考慮scale。

          最后,不斷討論和完善,每一個討論迭代都要得出一個實際的結論,避免持續停留在過高抽象層面。這里涉及的部分可以很多,包括可擴展性、數據規模、吞吐量、可維護性、實時性、數據一致性等等。

          所以,歸納起來的四部分為,先從系統外部理清楚需求,接著設計核心模型和API,再進行基本的分層和組件劃分,最后才是細化每一層或者每個組件的設計。從外到內,逐層剖析。

          這些點說起來容易做起來難,通過反復閱讀和思考一些常見的系統設計場景,其實我們還是可以從中總結出若干規律來。

          下面列出幾個非常常見和典型的系統設計問題的hints:

          1、怎樣設計一個微博/推ter系統(news feed系統)

          • 思考讀寫模型,latency上看明顯是讀的要求明顯高于寫的模式。
          • 轉發和回復,拷貝原微博文字還是存儲轉發/回復樹形關系?分析利弊。另外,這里涉及到產品設計,參見:推ter Vs. Weibo: 8 Things 推ter Can Learn From The Latter
          • 區分兩種典型消息傳播的觸發方式:push on change和pull on demand,兩種方式利弊明顯。參考:Why Are 非死book, Digg, And 推ter So Hard To Scale?
          • 存儲分級。這里CAP中A最為重要,往往C可以被犧牲,達到最終一致性。
          • 緩存設計,分層的數據流動?如何識別熱門?
          • 刪除微博功能的設計。

          2、怎樣設計一個短網址映射系統(tiny url系統)

          • 思考讀寫模型,明顯是讀優先級高于寫的服務,但是通常不需要修改。讀寫服務分離,在寫服務崩潰時保證讀服務健康運行。
          • 鏈接縮短使用的加密和映射的方式中,算法如何選擇?短鏈接可以接受那些字符?此處可以估算特定的規則下長度為n的短鏈接最多可能表示多少種實際鏈接。
          • 如果使用統一的短鏈接序列分配機制,如何分布式設計這個分配邏輯?它不能夠成為瓶頸。例如,一種常見的思路是讓關系數據庫的自增長索引給出唯一id,但是如果不使用關系數據庫,在分布式系統中如何產生唯一序列號且避免沖突?參考:如何在高并發分布式系統中生成全局唯一Id
          • 是否需要保留原始鏈接最后部分?如http://abc.def.com/p/124/article/12306.html壓縮成http://short.url/asdfasdf/12306.html,以增加可讀性。
          • 由于協議部分可以預見或者需要支持的數量很少(比如就支持http和https),是否可以考慮把協議部分略去,以枚舉方式和短鏈接正文放在一起?
          • 由于屬于web服務,考慮判定URL合法性,考慮怎樣控制請求流量和應對惡意訪問。

          還有一些系統設計典型和經典問題,想到的先列在下面,等后續有時間總結了再補充到上面去:

          • 搜索引擎設計(包括網頁爬蟲)
          • 郵件系統設計(例如GMail)
          • 聊天系統

          無論如何,對于這些問題的解決,思考是最有趣的環節。這些東西貌似可以直接拿來學習的材料比較少,而且也不像算法那樣丁是丁卯是卯的,評判的標準模糊得很。

          文章未經特殊標明皆為本人原創,未經許可不得用于任何商業用途,轉載請保持完整性并注明來源鏈接《四火的嘮叨》

 本文由用戶 y37f 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!