自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Pastebin設(shè)計(jì)之旅:從零設(shè)計(jì)網(wǎng)絡(luò)文本存儲系統(tǒng)

數(shù)據(jù)庫 其他數(shù)據(jù)庫
我們可以在數(shù)據(jù)庫中每個URL的條目里存儲訪問權(quán)限級別(公開/私有)。我們也可以創(chuàng)建一個單獨(dú)的表來存儲有權(quán)訪問特定URL的用戶的UserID。

項(xiàng)目簡介:Pastebin是一個在線的文本存儲平臺,讓用戶可以存儲和分享代碼片段或者其他類型的文本。它支持多種編程和標(biāo)記語言的語法高亮,用戶可以選擇讓他們的"paste"公開或私有。無需注冊就可以使用,但注冊用戶可以更方便地管理他們的"paste"。Pastebin常被開發(fā)者、系統(tǒng)管理員以及其他技術(shù)專業(yè)人員用于分享和協(xié)作。

現(xiàn)在讓我們來設(shè)計(jì)一個類似Pastebin的網(wǎng)絡(luò)服務(wù),用戶可以在這里儲存純文本。用戶可以輸入一段文本,并獲取一個隨機(jī)生成的URL來訪問這段文本。

類似的產(chǎn)品有:pastebin.com,controlc.com,hastebin.com,privatebin.net

系統(tǒng)難度等級:初級

1、什么是Pastebin

Pastebin及類似服務(wù)讓用戶能夠在網(wǎng)絡(luò)(通常指的是互聯(lián)網(wǎng))上存儲純文本或圖像,并生成唯一的URL來訪問上傳的數(shù)據(jù)。這樣的服務(wù)也被用來快速地在網(wǎng)絡(luò)上共享數(shù)據(jù),用戶只需傳遞URL,其他用戶就可以查看其內(nèi)容。

如果你以前沒有使用過pastebin.com,建議嘗試在那里創(chuàng)建一個新的“Paste”,并花些時間瀏覽他們服務(wù)提供的不同選項(xiàng)。這將在理解本章時有很大幫助。

對于類似于Pastebin這樣的代碼或文本分享平臺,中國并未有一款特別知名或廣泛使用的網(wǎng)站。很多開發(fā)者會使用GitHub Gist來分享代碼片段,此外,國內(nèi)也有一些代碼托管平臺,比如Coding.net和Gitee,也提供代碼分享和協(xié)作的功能。

2、系統(tǒng)的需求和目標(biāo)

Pastebin服務(wù)需要滿足以下要求:

功能需求

  1. 用戶應(yīng)能夠上傳或“粘貼”他們的數(shù)據(jù),并獲得一個獨(dú)特的URL來訪問它。
  2. 用戶只能上傳文本。
  3. 數(shù)據(jù)和鏈接將在特定的時間段后自動過期;用戶應(yīng)可以指定過期時間。
  4. 用戶可以選擇為他們的粘貼內(nèi)容設(shè)置一個自定義的別名。

非功能性需求

  1. 系統(tǒng)必須具有高度的可靠性,上傳的任何數(shù)據(jù)都不應(yīng)丟失。
  2. 系統(tǒng)必須始終可用。這是因?yàn)槿绻覀兊姆?wù)暫停,用戶將無法訪問他們的粘貼內(nèi)容。
  3. 用戶應(yīng)能實(shí)時訪問他們的粘貼內(nèi)容,延遲要最小。
  4. 粘貼的鏈接不能被輕易猜出(不能被預(yù)測)。

擴(kuò)展需求

  1. 分析,例如,一個粘貼內(nèi)容被訪問了多少次?
  2. 我們的服務(wù)也應(yīng)該通過REST APIs供其他服務(wù)訪問。

3、注意事項(xiàng)

Pastebin與URL縮短服務(wù)(系統(tǒng)設(shè)計(jì)上一個案例)有一些相同的需求,但是我們還應(yīng)該考慮一些額外的設(shè)計(jì)因素。

用戶每次粘貼的文本量應(yīng)有何限制?我們可以限制用戶不得粘貼超過10MB10MB10MB的數(shù)據(jù),以防止服務(wù)被濫用。

我們是否應(yīng)對自定義URL的大小設(shè)置限制?由于我們的服務(wù)支持自定義URL,用戶可以選擇他們喜歡的任何URL,但是提供自定義URL并非強(qiáng)制性的。然而,對自定義URL設(shè)置大小限制是合理的(而且通常是我們期望的),這樣我們可以保持一致的URL數(shù)據(jù)庫。

4、容量估計(jì)與約束

我們的服務(wù)將是讀取密集型的;相比新建Paste,讀取請求會更多。我們可以假設(shè)讀取與寫入之間的比例是5:1。

流量預(yù)估:Pastebin類似的服務(wù)并不預(yù)期有如微信或今日頭條那樣的流量,這里我們假設(shè)每天有一百萬個新的粘貼內(nèi)容添加到我們的系統(tǒng)中。這樣算來,我們每天有五百萬次的讀取。

每秒新粘貼內(nèi)容

1M / (24 小時 * 3600 秒) ~= 12 粘貼/秒

每秒粘貼讀取次數(shù)

5M / (24 小時 * 3600 秒) ~= 58 讀取/秒

存儲預(yù)估:用戶最多可以上傳10MB的數(shù)據(jù);一般來說,Pastebin類似的服務(wù)用于分享源代碼、配置文件或日志。這些文本并不大,所以我們假設(shè)每個粘貼內(nèi)容平均含有10KB10KB10KB。

按照這個速率,我們每天將存儲10GB的數(shù)據(jù)。

1M * 10KB => 10 GB/天

如果我們想將這些數(shù)據(jù)存儲十年,那我們總共需要36TB的存儲容量。

每天有1M的粘貼內(nèi)容,十年后我們將有36億的粘貼內(nèi)容。我們需要生成并存儲鍵來唯一地標(biāo)識這些粘貼內(nèi)容。如果我們使用Base64編碼([A-Z, a-z, 0-9, ., -]),我們將需要六個字符的字符串:

64^6 ~= 68.7億個唯一字符串

如果存儲一個字符需要一個字節(jié),存儲36億個鍵所需的總大小將是:

3.6B?6=>22GB

相比于36TB,22GB微不足道。為了保留一些余量,我們將假設(shè)一個70%的容量模型(意味著我們在任何時候都不希望使用超過總存儲容量的70%),這將使我們的存儲需求增加到 51.4TB。

帶寬預(yù)估:對于寫入請求,我們預(yù)計(jì)每秒新增12個粘貼內(nèi)容,導(dǎo)致每秒進(jìn)入120KB的數(shù)據(jù)。

12?10KB=>120KB/s

至于讀取請求,我們預(yù)計(jì)每秒58個請求。因此,總的數(shù)據(jù)出口(發(fā)送給用戶)將是0.6MB/s。

58?10KB=>0.6MB/s

盡管總的進(jìn)出口并不大,我們在設(shè)計(jì)服務(wù)時應(yīng)記住這些數(shù)字。

內(nèi)存預(yù)估:我們可以緩存一些被頻繁訪問的熱門粘貼內(nèi)容。根據(jù)80-20原則,意味著20%的熱門粘貼內(nèi)容產(chǎn)生了80%的流量,我們希望將這20%的粘貼內(nèi)容進(jìn)行緩存。

既然我們每天有500萬次的讀取請求,要緩存這些請求中的20%,我們需要:

0.2?5M?10KB =10GB

因此,我們大約需要10GB的內(nèi)存來緩存那些熱門的粘貼內(nèi)容。

5、系統(tǒng)API

我們可以有SOAP或REST API來公開我們服務(wù)的功能。以下是創(chuàng)建/檢索/刪除粘貼內(nèi)容的API定義:

addPaste(api_dev_key, paste_data, custom_url=None user_name=None, paste_name=None, expire_date=None)

參數(shù)

api_dev_key (字符串): 已注冊帳戶的API開發(fā)者密鑰。這將用于基于分配的配額對用戶進(jìn)行限流等操作。

paste_data (字符串): 粘貼的文本數(shù)據(jù)。

custom_url (字符串): 可選的自定義URL。

user_name (字符串): 可選的用于生成URL的用戶名。

paste_name (字符串): 粘貼內(nèi)容的可選名稱。

expire_date (字符串): 粘貼內(nèi)容的可選過期日期。

返回: (字符串)

成功插入返回可以訪問粘貼內(nèi)容的URL,否則,它將返回一個錯誤碼。

類似地,我們可以有檢索和刪除粘貼內(nèi)容的API:

getPaste(api_dev_key, api_paste_key)

其中api_paste_key是一個表示要檢索的粘貼內(nèi)容的粘貼鍵的字符串。這個API將返回粘貼內(nèi)容的文本數(shù)據(jù)。

deletePaste(api_dev_key, api_paste_key)

成功刪除返回true,否則返回false。

6、數(shù)據(jù)庫設(shè)計(jì)

關(guān)于我們存儲的數(shù)據(jù)性質(zhì),我們有一些觀察:

  1. 我們需要存儲數(shù)十億條記錄。
  2. 我們存儲的每個元數(shù)據(jù)對象都很?。ㄐ∮?KB)。
  3. 我們存儲的每個粘貼對象大小適中(可以達(dá)到幾MB)。
  4. 記錄之間沒有關(guān)系,除非我們要存儲哪個用戶創(chuàng)建了哪個粘貼內(nèi)容。
  5. 我們的服務(wù)主要是讀取操作。

數(shù)據(jù)庫架構(gòu)

我們需要兩個表,一個用于存儲粘貼內(nèi)容的信息,另一個用于存儲用戶的數(shù)據(jù)。

這里,URlHash是TinyURL的URL等效項(xiàng),ContentKey是指向一個外部對象的引用,該對象存儲粘貼內(nèi)容的內(nèi)容;我們將在本章后面討論粘貼內(nèi)容的外部存儲。

7、頂層設(shè)計(jì)

在頂層設(shè)計(jì)上,我們需要一個應(yīng)用層來處理所有的讀取和寫入請求。應(yīng)用層將與存儲層進(jìn)行通信,以存儲和檢索數(shù)據(jù)。我們可以將存儲層劃分為兩部分,一部分?jǐn)?shù)據(jù)庫存儲與每個粘貼內(nèi)容、用戶等相關(guān)的元數(shù)據(jù),另一部分將粘貼內(nèi)容存儲在某些對象存儲中(如阿里云OSS)。這種數(shù)據(jù)的劃分也允許我們單獨(dú)進(jìn)行擴(kuò)展。

8、組件設(shè)計(jì)

A. 應(yīng)用層

我們的應(yīng)用層將處理所有的進(jìn)出請求。應(yīng)用服務(wù)器將與后端數(shù)據(jù)存儲組件進(jìn)行通信以服務(wù)這些請求。

如何處理寫入請求?在收到寫入請求后,我們的應(yīng)用服務(wù)器將生成一個六位隨機(jī)字符串,這將作為粘貼的鍵(如果用戶沒有提供自定義鍵)。然后,應(yīng)用服務(wù)器將粘貼的內(nèi)容和生成的鍵存儲在數(shù)據(jù)庫中。成功插入后,服務(wù)器可以將鍵返回給用戶。這里可能存在的一個問題是由于鍵重復(fù)而導(dǎo)致插入失敗。由于我們是生成一個隨機(jī)鍵,所以新生成的鍵可能與現(xiàn)有的鍵相匹配。在這種情況下,我們應(yīng)該重新生成一個新的鍵并再試一次。我們應(yīng)該一直重試,直到我們不再因?yàn)橹貜?fù)鍵看到失敗。如果用戶提供的自定義鍵已經(jīng)在我們的數(shù)據(jù)庫中存在,我們應(yīng)該向用戶返回一個錯誤。

上述問題的另一種解決方案可能是運(yùn)行一個獨(dú)立的鍵生成服務(wù)(KGS),它提前生成隨機(jī)的六位字符串,并將它們存儲在數(shù)據(jù)庫中(我們稱之為key-DB)。每當(dāng)我們想要存儲一個新的粘貼,我們只需要取一個已經(jīng)生成的鍵并使用它。這種方法將使事情變得非常簡單和快速,因?yàn)槲覀儾粫?dān)心重復(fù)或碰撞。KGS將確保所有插入key-DB的鍵都是唯一的。

KGS可以使用兩個表來存儲鍵,一個用于尚未使用的鍵,一個用于所有已使用的鍵。一旦KGS向應(yīng)用服務(wù)器提供了一些鍵,它可以將這些移動到已使用的鍵表中。KGS可以始終在內(nèi)存中保持一些鍵,以便每當(dāng)服務(wù)器需要它們時,它可以快速提供。一旦KGS在內(nèi)存中加載了一些鍵,它就可以將它們移動到已使用的鍵表中;這樣我們就可以確保每個服務(wù)器獲取到的鍵都是唯一的。如果KGS在使用所有加載到內(nèi)存中的鍵之前死掉,我們將浪費(fèi)這些鍵。我們可以忽略這些鍵,因?yàn)槲覀冇写罅康逆I。

KGS會出現(xiàn)單點(diǎn)故障嗎?會的。為了解決這個問題,我們可以有一個備用的KGS副本,每當(dāng)主服務(wù)器死掉時,它可以接管來生成和提供鍵。

每個應(yīng)用服務(wù)器可以從key-DB中緩存一些鍵嗎?是的,這肯定可以加快速度。雖然在這種情況下,如果應(yīng)用服務(wù)器在消費(fèi)所有鍵之前死掉,我們將最終丟失那些鍵。這可能是可以接受的,因?yàn)槲覀冇?8B個唯一的六位字母鍵,這比我們需要的要多得多。

如何處理粘貼讀取請求?在收到讀取粘貼請求后,應(yīng)用服務(wù)層聯(lián)系數(shù)據(jù)存儲。數(shù)據(jù)存儲搜索鍵,如果找到了,就返回粘貼的內(nèi)容。否則,返回一個錯誤碼。

B. 數(shù)據(jù)存儲層

我們可以將我們的數(shù)據(jù)存儲層分為兩部分:

  1. 元數(shù)據(jù)數(shù)據(jù)庫:我們可以使用像MySQL這樣的關(guān)系數(shù)據(jù)庫,或者像Dynamo或Cassandra這樣的分布式Key-Value存儲。
  2. 對象存儲:我們可以將我們的內(nèi)容存儲在像阿里云OSS這樣的對象存儲中。每當(dāng)我們感覺到我們的內(nèi)容存儲容量已經(jīng)滿了,我們可以通過平臺直接擴(kuò)容。

9、數(shù)據(jù)分區(qū)和復(fù)制

為了擴(kuò)展我們的數(shù)據(jù)庫,我們需要對其進(jìn)行分區(qū),以便它能存儲數(shù)十億個URL的信息。因此,我們需要設(shè)計(jì)一個分區(qū)方案,將我們的數(shù)據(jù)劃分并存儲到不同的數(shù)據(jù)庫中。

A. 基于范圍的分區(qū):我們可以根據(jù)哈希鍵的第一個字母在不同的分區(qū)中存儲URL。因此,我們將所有以字母“A”(和“a”)開頭的URL哈希鍵存儲在一個分區(qū)中,將以字母“B”開頭的URL存儲在另一個分區(qū)中,以此類推。這種方法被稱為基于范圍的分區(qū)。我們甚至可以將某些出現(xiàn)頻率較低的字母組合到一個數(shù)據(jù)庫分區(qū)中。因此,我們應(yīng)開發(fā)一個靜態(tài)分區(qū)方案,始終以可預(yù)測的方式存儲/查找URL。

這種方法的主要問題是可能導(dǎo)致數(shù)據(jù)庫服務(wù)器不平衡。例如,我們決定將所有以字母“E”開頭的URL放入一個數(shù)據(jù)庫分區(qū),但后來我們發(fā)現(xiàn)以字母“E”開頭的URL過多。

B. 基于哈希的分區(qū):在這種方案中,我們對存儲的對象進(jìn)行哈希。然后,我們根據(jù)哈希值計(jì)算使用哪個分區(qū)。在我們的情況下,我們可以獲取key或短鏈接的哈希值,以確定我們存儲數(shù)據(jù)對象的分區(qū)。

我們的哈希函數(shù)將隨機(jī)地將URL分配到不同的分區(qū)(例如,我們的哈希函數(shù)可以始終將任何key映射到[1...256]之間的一個數(shù)字)。這個數(shù)字將表示我們存儲對象的分區(qū)。

這種方法仍然可能導(dǎo)致分區(qū)負(fù)載過大,這可以通過使用'一致性哈希'來解決。

10、緩存

我們可以緩存頻繁訪問的URL。我們可以使用任何現(xiàn)成的解決方案,比如Memcached,它可以存儲完整的URL及其對應(yīng)的哈希值。因此,應(yīng)用服務(wù)器在訪問后端存儲之前,可以快速檢查緩存是否有所需的URL。

我們應(yīng)該有多少緩存內(nèi)存?我們可以從日流量的20%開始,根據(jù)客戶的使用模式,我們可以調(diào)整需要多少緩存服務(wù)器。如上所估計(jì),我們需要170GB的內(nèi)存來緩存日流量的20%。目前的一些服務(wù)器可以擁有256GB的內(nèi)存,我們可以輕松將所有緩存放入一臺機(jī)器?;蛘?,我們可以使用幾臺小一點(diǎn)的服務(wù)器來存儲所有這些熱門URL。

哪種緩存驅(qū)逐策略最適合我們的需求?當(dāng)緩存滿了,我們想用一個新的/更熱門的URL替換一個鏈接,我們應(yīng)該如何選擇?最近最少使用(LRU)可能是我們系統(tǒng)的一個合理策略。根據(jù)這個策略,我們首先丟棄最近最少使用的URL。我們可以使用Linked Hash Map或類似的數(shù)據(jù)結(jié)構(gòu)來存儲我們的URL和哈希值,這也會記錄最近訪問過的URL。

為了進(jìn)一步提高效率,我們可以復(fù)制我們的緩存服務(wù)器來分配它們之間的負(fù)載。

每個緩存副本如何更新?每當(dāng)有一個緩存未命中,我們的服務(wù)器會訪問后端數(shù)據(jù)庫。當(dāng)這種情況發(fā)生,我們可以更新緩存,并將新的條目傳遞給所有的緩存副本。每個副本都可以通過添加新的條目來更新其緩存。如果副本已經(jīng)有了該條目,它可以簡單地忽略它。

11、負(fù)載均衡(LB)

我們可以在系統(tǒng)中的三個位置添加負(fù)載均衡層:

  • 客戶端與應(yīng)用服務(wù)器之間
  • 應(yīng)用服務(wù)器與數(shù)據(jù)庫服務(wù)器之間
  • 應(yīng)用服務(wù)器與緩存服務(wù)器之間

最初,我們可以使用一個簡單的輪詢方法,將進(jìn)入的請求均等地分配到后端服務(wù)器。這種負(fù)載均衡方法簡單易行,不會引入任何額外的開銷。這種方法的另一個優(yōu)點(diǎn)是,如果一個服務(wù)器死機(jī),負(fù)載均衡器會將其從輪詢中移除,停止向其發(fā)送任何流量。

輪詢負(fù)載均衡的一個問題是,我們沒有考慮到服務(wù)器的負(fù)載。如果一個服務(wù)器過載或運(yùn)行緩慢,負(fù)載均衡器不會停止向該服務(wù)器發(fā)送新的請求。為了處理這個問題,我們可以放置一個更優(yōu)的負(fù)載均衡解決方案,它定期查詢后端服務(wù)器的負(fù)載,并根據(jù)負(fù)載情況調(diào)整流量。

12、清除或數(shù)據(jù)庫清理

key條目是否應(yīng)永久存在,還是應(yīng)該被清除?如果達(dá)到用戶設(shè)定的過期時間,鏈接應(yīng)該怎么處理?

如果我們選擇持續(xù)尋找過期鏈接并將其刪除,這將對我們的數(shù)據(jù)庫產(chǎn)生很大壓力。相反,我們可以慢慢地刪除過期的鏈接,進(jìn)行懶人清理。我們的服務(wù)將確保只刪除過期的鏈接,盡管有些過期鏈接可能會存在更長時間,但永遠(yuǎn)不會被返回給用戶。

  • 每當(dāng)用戶試圖訪問一個已過期的鏈接,我們可以刪除該鏈接并向用戶返回錯誤。
  • 我們可以設(shè)置一個單獨(dú)的清理服務(wù),定期從我們的存儲和緩存中刪除過期的鏈接。這個服務(wù)需要非常輕量,只在預(yù)計(jì)用戶流量較低的時候運(yùn)行。
  • 我們可以為每個鏈接設(shè)定一個默認(rèn)的過期時間(例如兩年)。
  • 刪除過期鏈接后,我們可以將該Key重新放回Key-DB,以供重復(fù)使用。
  • 我們是否應(yīng)刪除一段時間(比如說六個月)內(nèi)沒有被訪問過的鏈接?這可能有點(diǎn)不合適。由于存儲成本越來越低,我們可以決定永久保存鏈接。

13、數(shù)據(jù)跟蹤

我們?nèi)绾谓y(tǒng)計(jì)短鏈接被使用的次數(shù)、用戶的位置等信息?我們?nèi)绾蝺Υ孢@些統(tǒng)計(jì)信息?如果它是數(shù)據(jù)庫中的一部分,每次查看都需要更新,那么當(dāng)一個流行的短鏈接被大量并發(fā)請求瞬間涌入時,會發(fā)生什么?

一些值得追蹤的統(tǒng)計(jì)數(shù)據(jù):訪客的國家、訪問的日期和時間、引導(dǎo)點(diǎn)擊的網(wǎng)頁、訪問頁面的瀏覽器或平臺。

14、安全和權(quán)限

用戶能否創(chuàng)建私有URL或者允許特定的用戶組訪問某個URL?

我們可以在數(shù)據(jù)庫中每個URL的條目里存儲訪問權(quán)限級別(公開/私有)。我們也可以創(chuàng)建一個單獨(dú)的表來存儲有權(quán)訪問特定URL的用戶的UserID。如果一個用戶沒有權(quán)限但試圖訪問一個URL,我們可以返回一個錯誤(HTTP 401)??紤]到我們的數(shù)據(jù)儲存在一個類似Cassandra的NoSQL寬列數(shù)據(jù)庫中,儲存權(quán)限的表的key將是‘哈希值’(或KGS生成的key)。列將儲存有權(quán)查看URL的用戶的UserID。

責(zé)任編輯:武曉燕 來源: 今日頭條
相關(guān)推薦

2018-03-07 10:35:45

云計(jì)算存儲系統(tǒng)

2009-10-14 14:56:19

網(wǎng)絡(luò)綜合布線系統(tǒng)

2023-07-12 08:44:46

湖倉存儲系統(tǒng)數(shù)據(jù)湖

2017-07-04 10:58:57

SAN存儲網(wǎng)絡(luò)存儲系統(tǒng)架構(gòu)

2011-09-05 09:23:50

2017-10-25 08:44:03

NVMe SSD數(shù)據(jù)存儲

2012-12-28 17:31:06

2018-09-29 14:08:04

存儲系統(tǒng)分布式

2024-11-11 08:31:32

2015-06-16 11:51:17

百度云NoSQLAtlas

2024-11-25 09:10:03

2019-01-28 11:46:53

架構(gòu)運(yùn)維技術(shù)

2022-08-08 16:33:24

智能建筑樓宇自控物聯(lián)網(wǎng)

2016-12-05 18:11:29

2018-01-31 08:44:20

數(shù)據(jù)存儲存儲設(shè)備存儲系統(tǒng)

2018-01-19 08:35:47

存儲系統(tǒng)SAS

2017-11-08 11:22:46

存儲趨勢系統(tǒng)

2021-10-12 19:01:35

網(wǎng)站頁眉導(dǎo)航

2019-06-17 23:25:04

NebulasFs架構(gòu)分布式

2015-03-20 10:13:34

IP存儲網(wǎng)絡(luò)博科EMC
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號