<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 為社交產品設計后端 > 原文: [http://highscalability.com/blog/2015/7/22/architecting-backend-for-a-social-product.html](http://highscalability.com/blog/2015/7/22/architecting-backend-for-a-social-product.html) ![](https://img.kancloud.cn/4c/6e/4c6ed1fbca7526ceb73d869e1ef92d55_240x120.png) 旨在幫助您做出關鍵的體系結構決策,這將使社交應用程序成為真正的下一代社交產品。 提議的更改解決了以下屬性: a)可用性 b)可靠性 c)可擴展性 d)擴展的性能和靈活性(非修改) ## 目標 a)確保用戶的內容易于發現并且始終可用。 b)確保推送的內容不僅在語義上相關,而且從用戶的設備角度來看也相關。 c)確保生成,推送和分析實時更新。 d)著眼于盡可能節省用戶的資源。 e)無論服務器負載如何,用戶的體驗都應保持不變。 f)確保整體應用程序安全性 總而言之,我們要應對一個巨大的挑戰,我們必須應對龐大的海量,不斷擴大的用戶生成內容,不斷增加的用戶數量以及源源不斷的新商品,同時還要確保出色的性能。 考慮到上述挑戰,我們必須研究某些會影響整個系統設計的關鍵體系結構元素。 以下是一些關鍵決策&分析。 ### 數據存儲 數據存儲和數據建模是要做出的關鍵決定之一。 社交產品有望處理多種類型的數據,因此,在為每種類型選擇模型和存儲之前,我們必須全面分析和理解數據,這一點至關重要。 第一步是確定哪些是最頻繁查詢的數據,哪些不是那么頻繁需要的數據(用于分析的存檔數據)。 對于期望以較高頻率查詢的數據,需要將其放置在始終可用的位置,以便更快地讀寫和水平擴展。 現在,即使我們的用例并未強制使用基于 RDBMS 的系統,我們仍將 MySQL 用于所有用例。 隨著數據的增長,我們的讀寫將成為應用程序性能的瓶頸。 我們應該準備好每秒處理數十億次查詢。 讓我們對數據進行分類: a)主數據或靜態形式的數據,例如用戶個人資料 b)語義數據 c)用戶生成的內容 d)會話數據 對于我們來說,要找到對所有這些類型的數據都具有高性能的數據存儲確實是很難的。 因此,我們將需要為每個數據庫選擇特定的數據存儲。 **靜態數據**:對于靜態數據,最好選擇基于文檔的鍵和值都可查詢的存儲。 我們可以在這里選擇建立良好的基于??文檔的存儲,例如 MongoDB。 選擇 MongoDB 的最大優點是它在文檔級別提供 ACID 屬性。 它可以輕松地在多個分布式數據中心內和跨多個數據中心進行擴展。 這將使我們能夠使用副本集輕松維護冗余,從而解決我們的可用性問題。 分片是另一個要考慮的大因素,這對于確保規模&速度至關重要。 幸運的是,MongoDB 支持透明地分片。 **關聯數據或關系數據(核心數據)**:我們的數據的大部分將在自然界中關聯,例如,A 是 B 的朋友,C 是 A 和 B 的朋友。此類數據是高度語義化的數據 最適合建模為圖形。 我們應該將這些數據存儲在像 Neo4j 這樣的圖形數據庫中。 優勢顯而易見; 它將使我們能夠存儲節點的所有連接以及節點本身,從而節省了計算連接數據之間關系的額外步驟。 圖形數據模型還將在這里幫助我們捕獲關系的屬性。 當嘗試探索連接的數據時,屬性豐富的關系絕對至關重要。 GraphDB 支持 ACID 規則和自動索引。 同樣,我們在可用性和可伸縮性方面的要求是相同的。 我們可以有成百上千的并發事務全部同時寫入數據庫以及成千上萬的讀取。 它應該擴展為每秒處理多個 PB 數據集中的十億次讀取。 我們需要一個允許動態縮放讀寫的系統。 要考慮的另一個因素是分片,這對于擴展我們的系統至關重要。 Neo4j 已經設計成可水平擴展,并具有復制功能以保證可用性。 但截至目前,它不支持分片。 選擇一個時,我們可能需要更多分析。 其他選項是 FlockDB,AllegroGraph 和 InfiniteGraph。 **二進制數據(UGC)**:我們還必須處理與用戶相關的大量二進制數據。 考慮到二進制數據的大小,要處理它并不容易。 像上面討論的那樣,我們的系統是一個需求可以在幾秒鐘之內運行的很高的系統(峰值),規模和可用性是決定存儲位置時要考慮的最關鍵因素。 我們不能在這里依靠文件系統來存儲我們的二進制數據。 我們必須考慮可用性和可伸縮性。 文件系統的緩存可能受 CPU 限制,因此使其冗余將需要大量的簿記工作。 相反,我們應該依靠已經可用的系統。 例如,Amazon S3,這是非常受歡迎的對象存儲,具有保證的可用性,并且具有彈性。 我們也可以考慮使用 Google Cloud Storage 或 Rackspace Cloud Files 等。但是就報價而言,S3 顯然是贏家。 S3 已經支持數據分區。 它根據高請求率和分區中的鍵數,通過將數據連續拆分為多個分區,從而水平擴展 S3。 但是重要的是要意識到僅存儲內容是不夠的,與這些內容相關聯的元數據需要可搜索,并且搜索必須足夠擴展和足夠快。 我們還可以在這里嘗試一些新事物,例如從圖像自動識別尺寸,基于上下文自動標記等,然后使用它們來驅動圖像的鍵*。 這是一個潛在的 IP 領域。 我們將在索引部分下研究索引需求。 但是現在,讓我們僅注意,我們將使用標識符存儲內容,該標識符可以在其他地方建立索引。 亞馬遜的 S3 似乎最適合這種情況。 ### 會話數據 重要的是認識并理解為什么我們需要考慮會話數據。 會話數據將幫助我們維護用戶的狀態。 而且這種狀態應該以與服務器無關的方式持續,以使我們的部署規模擴大。 這將有助于我們使設計保持足夠的靈活性,從而確保會話不會停留在特定的節點或服務器上。 我們必須以一種可以重新生成用戶實際會話的方式來保存會話信息,如果用戶會話終止,我們仍然可以幫助用戶從他離開的地方開始。 在我們的市場中,連接不那么可靠,并且通常會丟包,這一點尤其重要。 這些數據需要在我們的所有節點上都可用,因此需要可用性和可伸縮性。 首先,我們可以很好地將其保存在我們的 MongoDB 中。 稍后我們可以考慮將其轉移到像 REDIS 這樣的純鍵值存儲中。 注意:所有推薦和脫機作業都應僅在非服務節點上運行。 ### 索引編制 索引對于我們的系統至關重要。 用戶可以搜索任何內容,這是我們的主要用例之一。 為了提高搜索性能,我們必須非常重視索引編制。 這里有兩件事要考慮。 首先是創建索引本身,其次是創建索引系統。 為了使有意義的可搜索系統,我們必須設計一個實時索引,該索引被倒置并在生成的內容窗口上工作。 首先,我們可以編寫一個非常簡單的系統,在內容攝取期間,該系統可以負責根據內容生成反向索引。 后來,隨著內容攝取負載的增加,我們可以簡單地用實時數據處理引擎(例如 Apache Storm)來代替它,這是一個分布式,容錯且高度可擴展的系統。 它可以接管索引邏輯的生成。 索引系統:Lucene 因其受歡迎程度和速度而成為顯而易見的選擇。 其性能無與倫比。 我們應該選擇 SolrCloud。 它已經支持透明分片,復制,并且具有讀寫側容錯功能。 ### 排隊&推送通知 每次在我們的應用中觸發事件時,我們都將被要求以通知的形式將該事件散發給他/她的關注者/朋友。 重要的是,我們的系統不要錯過任何這些信號,萬一發生故障,恢復這些事件至關重要。 為了做到這一點,我們必須尋找一個排隊解決方案。 我們可以使用 ActiveMQ,這是最可靠的排隊軟件。 它允許群集以實現高可用性,并支持分布式排隊。 推送通知是另一個要向我們的用戶發送通知的區域。 在這里,我們需要尋找規模。 我們應該為數十億個 nps 的規模做好準備。 這里有很多選項,但也許 pyapns,CommandIQ 和 App Booster 是最受歡迎的選項。 我們將需要專門管理一些事務,以確保即使用戶的設備處于離線狀態,也能確保通知的傳遞。 我建議我們實現一個基于雙指針的系統,該系統維護通知的狀態并在后臺將其寫入磁盤。 因此,每次通知失敗時,都會維護其狀態并使用狀態標志將其添加到重試隊列中。 最終,在傳遞通知時,將其出隊。 ### 緩存策略 像我們這樣的系統,我們的目標是使其擴展到十億 rps,因此智能緩存至關重要。 我們的設計將需要邏輯以多層緩存并智能地逐出它們。 讓我們從頂級看什么要緩存和在哪里緩存。 *應用程序級緩存(內容緩存)* :為了最大程度地減少緩存未命中并確保緩存始終保持最新的可用數據,我們必須尋找永不過時且始終可用的緩存 數據。 從本質上講,這意味著在我們所有的一般用例中,我們將不必查詢數據庫,從而節省了大量資源。 我們還應確保緩存的數據始終采用不需要任何消息傳遞且可以隨時呈現的格式。 實質上,這意味著我們會將在線負載轉換為離線負載,從而節省了延遲。 為此,我們必須確保每次將內容提取到系統中時,我們都要做兩件事 a)以一種在服務階段不需要任何消息傳遞的方式對原始內容進行非規范化,然后將其保存到緩存中。 為了安全起見,我們將始終設置一個有效期限,該期限可以足夠高。 b)原始內容也按原樣寫入我們的數據存儲中。 我們非常可以依靠 REDIS 來獲得此緩存,這是具有良好故障恢復能力的內存緩存。 它具有高度的可擴展性,較新的版本也允許透明分片。 并且它也支持主從節點配置。 最好的部分是它將使我們能夠按原樣保留本地數據結構,這使得增量寫入非常容易,并且對我們支持內容提要(扇出)至關重要。 還要注意的是,我們將需要在大型內容對象上進行大量的讀取-修改-寫入操作和少量讀取操作,以支持實時扇出,并且從速度的角度來看,REDIS 最適合這些操作。 *代理緩存 e* :反向代理級別的緩存也很關鍵。 它有助于減少服務器的負載,從而保持延遲。 但是,要使代理服務器真正有效地進行緩存,正確設置 HTTP 響應標頭至關重要。 有很多選擇,但流行的是 nginx 和 ATS。 *二級緩存(代碼級緩存)* :這是實體數據的本地存儲,以提高應用程序的性能。 通過減少昂貴的數據庫調用,使實體數據保持在應用程序本地,它有助于提高性能。 EhCache 是??該領域的熱門選擇。 *客戶端緩存* :這是實際的設備或瀏覽器緩存。 所有靜態項目應盡可能多地被高速緩存。 如果 API 響應設置了正確的 HTTP 緩存頭,則已經緩存了許多與資源相關的項目。 我們應該確保它按預期工作。 除此之外,我們應該使用設備自己的內存或使用 sqlite 來緩存盡可能多的其他內容。 所有昂貴的對象都應緩存。 例如 NSDateFormatter & NSCalendar,它的初始化速度很慢,應盡可能重復使用。 iOS Lot 可以在這里進行調整和使用,但這不在我們的研究范圍之內。 ### 內容壓縮 考慮到以下事實:我們主要希望用戶處理大量圖像和視頻,而這些圖像和視頻需要下載大量數據,因此優化下載大小至關重要。 它將為用戶節省數據并提高應用程序性能。 要考慮的其他方面是我們的網絡,我們的用戶主要使用 2.5g 或 3g 的非 LTE 網絡,其中帶寬通常是一個問題,并且連接不可靠。 數據使用成本也很高。 在這種情況下,智能壓縮是至關重要的。 但是壓縮圖像和視頻并不是那么簡單,通常需要更深入的分析。 我們處理的圖像和視頻可能是無損的,也有損的,這取決于用戶的設備質量。 因此,我建議使用多種壓縮技術來處理這種情況。 在這種情況下,我們可以嘗試幀內壓縮和幀間壓縮技術。 但是總的來說,我們可以為所有壓縮需求使用 zpaq 和 fp8。 我們也可以嘗試 WebP,這可能對我們的市場有利。 通常,我們將在整個過程中始終使用 GZIP,所有 API 響應都將始終進行 GZIP 處理。 ### 內容轉碼 考慮到我們將需要處理具有多個 OS 和屏幕分辨率的多個設備,因此我們的內容存儲和處理應與設備無關。 但是服務層應根據具體情況而定,并應根據用戶的設備功能理解并提供正確的內容。 這使得對我們的圖像和視頻進行轉碼至關重要。 我們的應用應收集有關內存,編碼和屏幕分辨率的設備功能,并將其作為上下文傳遞給我們的 API。 我們的 API 應該使用此上下文來修改/選擇內容版本。 根據收到的設備上下文,我們可以將內容預轉碼為幾個最受請求的版本。 對于轉碼,我們可以使用 FFMPEG,這是最可靠,使用最廣泛的框架。 我們可以根據需要修改 FFMPEG。 這也必須在攝取側完成。 ### 傳輸協議 考慮到我們的網絡場景(非 LTE,不可靠的連接等),至關重要的是要盡可能智能地節省資源并盡可能減少通信量。 我建議對所有 HTTP 請求都使用 OkHttp 客戶端,而反過來又使用 SPDY,SPDY 可以很好地抵抗連接失敗并透明地恢復。 對于我們所有的消息傳遞需求,我們應該切換到 MQTT,這是一種輕量級的機器到機器連接協議。 ### 安全 保護我們的應用程序確實很重要。 我們的整體體系結構應適應這一重要屬性。 在這里,我僅討論支持安全性所需的體系結構更改,而不會涉及實現性更改。 我們必須在架構中添加以下內容: 1.我們所有的用戶數據都必須加密。 MongoDB 和 Neo4j 已經支持存儲加密。 根據情況,我們可以決定對關鍵用戶信息進行加密。 必須為所有與數據庫相關的調用啟用傳輸加密。 2.安全套接字層:到我們的代理服務器的所有呼叫均應進行 SSL 加密。 代理服務器可以充當 SSL 終止點。 3.我們所有的 api 端點都應在非默認端口上運行,并且應實現 Oauth 而不失敗。 4.從 DB 進行的所有讀取應始終通過其余端點進行。 5.保存密碼的配置必須特別處理。 必須對密碼進行哈希處理,并且文件應被限制為只有應用程序才能在啟動時讀取該密碼。 這使我們可以通過文件系統權限來控制應用程序身份實例。 只有應用程序用戶可以閱讀,但不能寫,其他任何人都不能閱讀。 所有這些配置都可以打包在 keydb 下,并受 pwd 限制。 ## 組件 這是我們架構的組成部分: 1.負載均衡器:這是一層,它根據確定的策略確定將請求轉發到哪個代理服務器。 該層還將通過基于容量重定向流量來幫助我們保證可用性。 2.代理服務器:所有來電都必須在此處登陸。 這也是我們的 SSL 終止點。 它根據定義的策略緩存 HTTP 請求。 FE 層:此層運行節點服務器。 3.提取引擎:此組件處理所有傳入的內容。 它包含與非規范化,代碼轉換,緩存等有關的策略。將來,如果需要,可以在此處完成所有內容的充實。 4\. REST Server:這是與所有 DB 進行對話并生成響應的層。 其訪問受 Oauth 保護。 它可能是一個已實現邊緣緩存的 tomcat 容器。 5.事件處理器:此層處理所有事件,并且主要負責扇出功能。 它讀取 ActiveMQ 并使用通知引擎生成通知。 6.推薦引擎:此組件通過分析從用戶活動中收集到的所有信號來推動推薦。 根據收集到的實際信號,我們可以部署各種基于親和力的算法。 我們可以在 Apache Mahout 上進行回復,首先它已經提供了各種算法接口 系統的邏輯視圖: ![](https://img.kancloud.cn/23/83/2383c11bc0d5d9db5ac3c86866ded4de_379x500.png) # 結論 這更多是對關鍵組件的高級分析。 如果需要實施該建議,則不必一 implemented 而就,可以分階段進行,但是如果我們需要擴展和支持實際用例,則必須遵循我在此處提出的模式。 我沒有涉及任何設計領域。 那是在設計階段,將需要更深入的分析和了解系統的當前狀態。 [On HackerNews](https://news.ycombinator.com/item?id=9930752) 誰寫的? 讓他們停下來。 當他們說“很幸運,mongodb 音階”時,我停止閱讀(意譯) 寫得好。 非常喜歡閱讀。 這可能不適用于所有但定義良好的設計替代方案和分析。 愛它。 我很喜歡它。 僅需注意一點,ActiveMQ 既好又穩定,但值得探索 Kafka。 我覺得在可伸縮性方面要好得多。 總體來說真的很喜歡你的邏輯。 本文概述了針對特定功能(緩存,反向代理,負載平衡,通知等)的推薦軟件/應用程序,并在某種程度上說明了選擇的原因。 但是我認為,如果將組件抽象出來并且將更多的注意力放在系統的實際體系結構上,將會更有幫助。 例如,我在架構圖上看不到任何特定于領域的語言(我無法確定應用程序在做什么),而是一組完成功能的工具。 非常豐富。 您是否考慮使用關系數據庫而不是使用 mongodb 進行分片? 還是其他任何數據庫才可以進入?
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看