<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          系統(tǒng)設(shè)計(jì)實(shí)踐 (03) - Instagram社交服務(wù)

          共 7514字,需瀏覽 16分鐘

           ·

          2021-09-17 18:34

          前言

          系統(tǒng)設(shè)計(jì)實(shí)踐篇的文章將會(huì)根據(jù)《系統(tǒng)設(shè)計(jì)面試的萬(wàn)金油》[1]為前置模板,講解數(shù)十個(gè)常見(jiàn)系統(tǒng)的設(shè)計(jì)思路。

          前置閱讀:

          ?《系統(tǒng)設(shè)計(jì)面試的萬(wàn)金油》[2]?系統(tǒng)設(shè)計(jì)實(shí)踐(01) - 短鏈服務(wù)[3]?系統(tǒng)設(shè)計(jì)實(shí)踐(02) - 文本存儲(chǔ)服務(wù)[4]

          設(shè)計(jì)目標(biāo)

          讓我們?cè)O(shè)計(jì)一個(gè)像Instagram這樣的照片分享的社交網(wǎng)站,用戶可以上傳照片分享給其他用戶。

          一. 什么是Instagram?

          Instagram是一種社交網(wǎng)絡(luò)服務(wù),用戶可以上傳和分享自己的照片、視頻給其他用戶。Instagram用戶可以選擇公開(kāi)或私下分享信息。公開(kāi)共享的內(nèi)容都可以被任何其他用戶看到,而私有共享的內(nèi)容只能被指定的一組人訪問(wèn)。Instagram還允許用戶通過(guò)Facebook、Twitter、Flickr和Tumblr等其他社交網(wǎng)絡(luò)平臺(tái)進(jìn)行分享。

          在此,我們計(jì)劃設(shè)計(jì)一個(gè)更簡(jiǎn)單的Instagram,用戶可以分享照片,也可以關(guān)注其他用戶。每個(gè)用戶的動(dòng)態(tài)消息將包含該用戶關(guān)注的所有人的照片動(dòng)態(tài)。

          二. 系統(tǒng)的需求與目標(biāo)

          在設(shè)計(jì)Instagram時(shí),我們將重點(diǎn)關(guān)注以下需求

          功能性需求

          1.用戶可以上傳下載查看照片2.用戶可以根據(jù)視頻或者照片標(biāo)題搜索3.用戶之間可以互相關(guān)注4.該系統(tǒng)應(yīng)該能夠生成并顯示用戶關(guān)注的所有人的熱門(mén)照片組成的“新聞動(dòng)態(tài)(News Feed)”。

          非功能性需求

          1.我們的服務(wù)需要高可用性。2.對(duì)于好友動(dòng)態(tài)的生成,系統(tǒng)可接受的延遲是200ms。3.一致性可能會(huì)受到影響(出于可用性的考慮),如果用戶一段時(shí)間沒(méi)有看到照片,應(yīng)該沒(méi)問(wèn)題4.系統(tǒng)應(yīng)高度可靠;任何上傳的照片或視頻都不能丟失。

          不用考慮

          給照片添加標(biāo)簽,在標(biāo)簽上搜索照片,在照片上評(píng)論,給照片用戶加標(biāo)簽,跟蹤誰(shuí),等等

          三. 系統(tǒng)分析

          該系統(tǒng)將具有大量的讀操作,因此我們將重點(diǎn)構(gòu)建一個(gè)能夠快速檢索照片的系統(tǒng)。

          1.實(shí)際上,用戶可以上傳任意多的照片。在設(shè)計(jì)該系統(tǒng)時(shí),有效的存儲(chǔ)管理應(yīng)該是一個(gè)關(guān)鍵因素。2.在查看照片時(shí),預(yù)計(jì)延遲較低。3.數(shù)據(jù)應(yīng)該是100%可靠的。如果用戶上傳了一張照片,系統(tǒng)將保證它永遠(yuǎn)不會(huì)丟失。

          四. 容量估計(jì)與約束

          ?假設(shè)我們有5億用戶,每天有100萬(wàn)活躍用戶?每天200萬(wàn)張新照片,每秒23張。?平均照片文件大小=> 200KB?一天照片需要的存儲(chǔ)量

          2M * 200KB => 400 GB

          ?十年需要的存儲(chǔ)空間

          400GB * 365(day a year) * 10 (years) ~= 1425TB



          五. 高級(jí)設(shè)計(jì)

          在高級(jí)設(shè)計(jì)中,我們需要支持兩種方案,一種是上傳圖片,另一種是查看和搜索圖片。

          我們需要對(duì)象存儲(chǔ)服務(wù)器來(lái)存儲(chǔ)照片,還需要一些數(shù)據(jù)庫(kù)服務(wù)器來(lái)存儲(chǔ)關(guān)于照片的元數(shù)據(jù)信息。

          六. 數(shù)據(jù)庫(kù)設(shè)計(jì)

          早期階段定義DB模型將有助于理解不同組件之間的數(shù)據(jù)流,并在之后進(jìn)行數(shù)據(jù)分區(qū)

          我們需要存儲(chǔ)用戶、用戶上傳的照片以及用戶關(guān)注的人的數(shù)據(jù)。照片表將存儲(chǔ)一張照片相關(guān)的所有數(shù)據(jù),我們需要在(PhotoID, CreationDate)上有一個(gè)索引,因?yàn)槲覀冃枰@取最近的照片。

          PhotoUserUserFollow
          [PK] Photo ID: int[PK] UserID: int[PK] UserID1: int
          UserID: intName: varchar(20)[PK] UserID2: int
          PhotoPath: varchar(256)Email: varchar(20)
          PhotoLatitude: intDateOfBirth: datetime
          PhotoLongitude: intCreationDate: datetime
          UserLatitude: intLastLoginDate: datetime
          UserLongitude: int

          CreationDate: datetime

          存儲(chǔ)上述表結(jié)構(gòu)的一種簡(jiǎn)單方法是使用像MySQL這樣的RDBMS,因?yàn)槲覀冇羞B表查詢(xún)的場(chǎng)景。但是關(guān)系數(shù)據(jù)庫(kù)也存在其他挑戰(zhàn)。關(guān)于細(xì)節(jié)請(qǐng)參閱SQL vs NoSQL[5]

          我們可以將照片存儲(chǔ)在像HDFS或S3這樣的分布式文件存儲(chǔ)中,將上述表結(jié)構(gòu)存儲(chǔ)在分布式鍵值存儲(chǔ)中,以享受NoSQL提供的好處。所有與照片相關(guān)的元數(shù)據(jù)都可以進(jìn)入一個(gè)表,其中的鍵是PhotoID,值是一個(gè)包含PhotoLocation、UserLocation、CreationTimestamp等的對(duì)象。

          我們需要存儲(chǔ)用戶和照片之間的關(guān)系,知道誰(shuí)擁有哪張照片。我們還需要存儲(chǔ)用戶關(guān)注的人的列表。對(duì)于這兩個(gè)表,我們可以使用像Cassandra這樣的寬列數(shù)據(jù)存儲(chǔ)。對(duì)于UserPhoto表,鍵是UserID,值是用戶擁有的PhotoID列表,存儲(chǔ)在不同的列中。對(duì)于UserFollow表,我們將有一個(gè)類(lèi)似的方案。

          一般來(lái)說(shuō),Cassandra或鍵值存儲(chǔ)總是維護(hù)一定數(shù)量的副本,以提供可靠性。此外,在這樣的數(shù)據(jù)存儲(chǔ)中,刪除操作不會(huì)立即生效,數(shù)據(jù)在從系統(tǒng)中永久刪除之前會(huì)保留幾天(以支持反刪除)。

          七. 數(shù)據(jù)估算

          讓我們估算一下每個(gè)表中會(huì)有多少數(shù)據(jù),以及10年里我們總共需要多少存儲(chǔ)空間。

          用戶表

          假設(shè)每個(gè)intdateTime都是四個(gè)字節(jié),那么用戶表中的每一行都是 68 個(gè)字節(jié)

          UserID (4 bytes) + Name (20 bytes) + Email (32 bytes) + DateOfBirth (4 bytes) + CreationDate (4 bytes) + LastLogin (4 bytes) = 68 bytes

          如果我們有5億用戶,我們將需要32GB的總存儲(chǔ)空間。

          500 million * 68 ~= 32GB

          照片表

          Photo表中的每一行都是284字節(jié)

          PhotoID (4 bytes) + UserID (4 bytes) + PhotoPath (256 bytes) + PhotoLatitude (4 bytes) + PhotLongitude(4 bytes) + UserLatitude (4 bytes) + UserLongitude (4 bytes) + CreationDate (4 bytes) = 284 bytes

          如果每天有2M的新照片上傳,我們一天需要0.5GB的存儲(chǔ)空間

          2M * 284 bytes ~= 0.5GB per day

          未來(lái)10年,我們需要1.88TB的存儲(chǔ)空間。

          用戶關(guān)注表

          UserFollow表中的每一行都由8個(gè)字節(jié)組成。如果我們有5億用戶,平均每個(gè)用戶關(guān)注500個(gè)用戶。我們需要1.82TB的存儲(chǔ)空間來(lái)存儲(chǔ)UserFollow表。

          500 million users * 500 followers * 8 bytes ~= 1.82TB

          所有表10年所需的總空間為3.7TB

          32GB + 1.88TB + 1.82TB ~= 3.7TB

          八. 組件設(shè)計(jì)

          照片上傳(寫(xiě)操作)可能會(huì)很慢,因?yàn)樗鼈儽仨氝M(jìn)入磁盤(pán),而讀取將會(huì)更快,特別是當(dāng)它們是從緩存讀取來(lái)提供服務(wù)時(shí)。

          用戶上傳操作有可以消耗所有可用的連接,因?yàn)樯蟼魇且粋€(gè)緩慢的過(guò)程。這意味著如果系統(tǒng)忙于處理所有寫(xiě)入請(qǐng)求,則無(wú)法提供讀取服務(wù)。在設(shè)計(jì)我們的系統(tǒng)之前,我們應(yīng)該記住 Web 服務(wù)器有一個(gè)連接限制。如果我們假設(shè)一個(gè) Web 服務(wù)器同時(shí)最多可以有 500 個(gè)連接,那么它的并發(fā)上傳或讀取不能超過(guò) 500。為了解決這個(gè)瓶頸,我們可以將讀取和寫(xiě)入拆分為單獨(dú)的服務(wù)。我們將用于讀取的服務(wù)器和用于寫(xiě)入的服務(wù)器進(jìn)行分離,以確保上傳不會(huì)影響到讀取。

          九. 可靠性與冗余性

          我們需要保證用戶上傳的圖片不會(huì)丟失,并且可查看。因此,我們將為每個(gè)文件存儲(chǔ)多個(gè)副本,這樣,如果一個(gè)存儲(chǔ)服務(wù)器掛掉,我們可以從另一個(gè)存儲(chǔ)服務(wù)器上的副本檢索照片。

          同樣的原則也適用于系統(tǒng)的其他組件。如果我們希望系統(tǒng)具有高可用性,我們需要在系統(tǒng)中運(yùn)行多個(gè)服務(wù)副本,這樣,如果一些服務(wù)宕機(jī),系統(tǒng)仍然可用并在運(yùn)行。冗余消除了系統(tǒng)中的單點(diǎn)故障。

          如果在任何時(shí)刻只需要一個(gè)服務(wù)實(shí)例運(yùn)行,我們可以運(yùn)行不服務(wù)任何流量的服務(wù)的冗余輔助副本,但當(dāng)主服務(wù)器出現(xiàn)問(wèn)題時(shí),它可以在故障轉(zhuǎn)移后接管控制權(quán)。

          在系統(tǒng)中創(chuàng)建冗余可以消除單點(diǎn)故障,并在主節(jié)點(diǎn)出現(xiàn)問(wèn)題時(shí)提供備份或備用功能。例如,如果同一服務(wù)的兩個(gè)實(shí)例運(yùn)行在生產(chǎn)環(huán)境中,其中一個(gè)實(shí)例發(fā)生故障或降級(jí),則系統(tǒng)可以故障轉(zhuǎn)移到正常的副本。故障轉(zhuǎn)移可以自動(dòng)發(fā)生,也可以人工干預(yù)。

          十. 數(shù)據(jù)分片

          讓我們討論元數(shù)據(jù)分片的不同方案。

          方案一. 基于UserID分片

          假設(shè)我們基于UserID進(jìn)行分片,這樣我們就可以將一個(gè)用戶的所有照片保存在同一個(gè)分片上。如果一個(gè)DB Shard是1TB,那么我們需要4個(gè)shard來(lái)存儲(chǔ)3.7TB的數(shù)據(jù)。讓我們假設(shè)為了更好的性能和可伸縮性,我們保留10個(gè)分片

          因此,我們將根據(jù)UserID % 10找到分片數(shù),然后將數(shù)據(jù)存儲(chǔ)在那里。為了在我們的系統(tǒng)中唯一地識(shí)別任何照片,我們可以在每個(gè)PhotoID后面添加分片號(hào)。

          如何生成PhotoID? 每個(gè)DB分片都可以有自己的PhotoID自動(dòng)遞增序列,因?yàn)槲覀儗⒂妹總€(gè)PhotoID添加ShardID,它將使它在整個(gè)系統(tǒng)中獨(dú)一無(wú)二。

          這個(gè)分區(qū)方案有什么問(wèn)題

          ?我們將如何處理熱門(mén)用戶? 一些人關(guān)注這些熱門(mén)用戶,很多人看到他們上傳的任何照片。?有些用戶會(huì)比其他人擁有更多的照片,從而造成存儲(chǔ)的不均勻分布。?如果我們不能將一個(gè)用戶的所有圖片存儲(chǔ)在一個(gè)分片上,該怎么辦? 如果我們將一個(gè)用戶的照片分發(fā)到多個(gè)分片上會(huì)導(dǎo)致更高的延遲?將一個(gè)用戶的所有照片存儲(chǔ)在一個(gè)分片上可能會(huì)導(dǎo)致一些問(wèn)題,比如如果分片宕機(jī),所有用戶的數(shù)據(jù)都不可用,或者如果分片負(fù)載高,延遲會(huì)更高,等等。

          方案二. 基于PhotoID分片

          如果我們能先生成唯一的PhotoID,然后通過(guò)PhotoID % 10找到一個(gè)分片號(hào),那么上述問(wèn)題就解決了。在這種情況下,我們不需要在ShardID后面加上PhotoID,因?yàn)镻hotoID本身在整個(gè)系統(tǒng)中是唯一的。

          我們?cè)鯓硬拍苌蒔hotoIds?

          在這里,我們不能在每個(gè)Shard中使用自動(dòng)遞增序列來(lái)定義PhotoID,因?yàn)槲覀冃枰繮hotoID才能找到存儲(chǔ)它的Shard。一種解決方案是我們專(zhuān)門(mén)使用一個(gè)單獨(dú)的數(shù)據(jù)庫(kù)實(shí)例來(lái)生成自動(dòng)遞增的 ID(參考美團(tuán)Leaf實(shí)現(xiàn))。如果我們的 PhotoID 可以容納 64 位,我們可以定義一個(gè)只包含 64 位 ID 字段的表。所以每當(dāng)我們想在我們的系統(tǒng)中添加一張照片時(shí),我們可以在這個(gè)表中插入一個(gè)新行,并將該 ID 作為我們新照片的 PhotoID。

          生成DB的密鑰不是單點(diǎn)故障嗎?

          是的。解決方法是定義兩個(gè)這樣的數(shù)據(jù)庫(kù),一個(gè)生成偶數(shù)id,另一個(gè)生成奇數(shù)id。對(duì)于MySQL,下面的腳本可以定義這樣的序列。

          KeyGeneratingServer1:
              auto-increment-increment = 2
              auto-increment-offset = 1
          KeyGeneratingServer2:
              auto-increment-increment = 2
              auto-increment-offset = 2

          我們可以在這兩個(gè)數(shù)據(jù)庫(kù)前面放置一個(gè)負(fù)載均衡器,以便在它們之間進(jìn)行輪詢(xún)并處理。這兩個(gè)服務(wù)器可能不同步,其中一個(gè)生成的密鑰比另一個(gè)多,但這不會(huì)在我們的系統(tǒng)中造成任何問(wèn)題。我們可以通過(guò)為Users、Photo-Comments或系統(tǒng)中存在的其他對(duì)象定義單獨(dú)的ID表來(lái)擴(kuò)展這種設(shè)計(jì)。

          另外,我們可以實(shí)現(xiàn)一個(gè)密鑰生成方案,類(lèi)似于我們?cè)谠O(shè)計(jì)URL短鏈服務(wù)(如TinyURL)中討論過(guò)的方案KGS。

          如何規(guī)劃我們系統(tǒng)的未來(lái)發(fā)展?

          我們可以有大量的邏輯分區(qū)來(lái)適應(yīng)未來(lái)的數(shù)據(jù)增長(zhǎng),這樣以來(lái),多個(gè)邏輯分區(qū)駐留在單個(gè)物理數(shù)據(jù)庫(kù)服務(wù)器上。由于每個(gè)數(shù)據(jù)庫(kù)服務(wù)器上可以有多個(gè)數(shù)據(jù)庫(kù)實(shí)例,我們可以為任何服務(wù)器上的每個(gè)邏輯分區(qū)擁有單獨(dú)的數(shù)據(jù)庫(kù)。所以每當(dāng)我們覺(jué)得某個(gè)特定的數(shù)據(jù)庫(kù)服務(wù)器有很多數(shù)據(jù)時(shí),我們可以將一些邏輯分區(qū)從它遷移到另一臺(tái)服務(wù)器。我們可以維護(hù)一個(gè)配置文件(或一個(gè)單獨(dú)的數(shù)據(jù)庫(kù)),將我們的邏輯分區(qū)映射到數(shù)據(jù)庫(kù)服務(wù)器;這將使我們能夠輕松地移動(dòng)分區(qū)。每當(dāng)我們想要移動(dòng)一個(gè)分區(qū)時(shí),我們只需要更新配置文件來(lái)更改。

          十一. 好友動(dòng)態(tài)生成

          要為給定用戶創(chuàng)建好友動(dòng)態(tài)(類(lèi)似于朋友圈),我們需要獲取該用戶關(guān)注的人的最新、最受歡迎的照片。

          為簡(jiǎn)單起見(jiàn),假設(shè)我們需要為用戶的朋友圈獲取前 100 張照片。我們的應(yīng)用服務(wù)器將首先獲取用戶關(guān)注的人列表,然后從每個(gè)用戶獲取最新 100 張照片的元數(shù)據(jù)信息。在最后一步,服務(wù)器將所有這些照片提交給我們的排名算法,該算法將確定前 100 張照片(基于時(shí)間維度、相似度等)并將它們返回給用戶。這種方法的問(wèn)題是延遲很高,因?yàn)槲覀儽仨毑樵?xún)多個(gè)表并對(duì)結(jié)果執(zhí)行排序/合并/排名。為了提高效率,我們可以預(yù)先生成好友動(dòng)態(tài)數(shù)據(jù)并將其存儲(chǔ)在單獨(dú)的表中。

          預(yù)生成好友動(dòng)態(tài): 我們可以使用專(zhuān)門(mén)服務(wù)器,不斷生成用戶好友動(dòng)態(tài)數(shù)據(jù)并將它們存儲(chǔ)在UserNewsFeed表中。因此,當(dāng)任何用戶需要查看他的好友動(dòng)態(tài)照片時(shí),我們只需查詢(xún)這個(gè)表并將結(jié)果返回給用戶。

          每當(dāng)服務(wù)器需要生成用戶的NewsFeed時(shí),它們將首先查詢(xún)UserNewsFeed表,以查找最后一次為該用戶生成好友動(dòng)態(tài)的時(shí)間。然后,新的好友動(dòng)態(tài)數(shù)據(jù)將從那時(shí)起生成(按照上面提到的步驟)。

          向用戶發(fā)送動(dòng)態(tài)消息內(nèi)容有哪些不同的方法?

          ?拉模式: 客戶可以定期或在需要的時(shí)候手動(dòng)從服務(wù)器拉出好友動(dòng)態(tài)內(nèi)容。這種方法可能存在的問(wèn)題是:

          ?直到客戶端發(fā)出拉取請(qǐng)求時(shí),新數(shù)據(jù)可能不會(huì)顯示給用戶;?如果沒(méi)有新數(shù)據(jù),大多數(shù)情況下拉取請(qǐng)求會(huì)導(dǎo)致空響應(yīng)

          ?推模式 : 服務(wù)器可以在新數(shù)據(jù)可用時(shí)將其推送給用戶。為了有效地管理這一點(diǎn),用戶必須在服務(wù)器上維護(hù)一個(gè)Long Poll請(qǐng)求以接收更新。這種方法可能存在的一個(gè)問(wèn)題是,一個(gè)關(guān)注了很多人的用戶,或者一個(gè)擁有數(shù)百萬(wàn)粉絲的名人用戶;在這種情況下,服務(wù)器必須非常頻繁地推送更新。?混合模式 : 我們可以采用混合方法。我們可以將所有擁有大量關(guān)注的用戶轉(zhuǎn)移到基于拉取的模型,并且只將數(shù)據(jù)推送給那些擁有數(shù)百(或數(shù)千)關(guān)注的用戶。另一種方法可能是服務(wù)器以不超過(guò)一定頻率向所有用戶推送更新,讓有大量關(guān)注/更新的用戶定期拉取數(shù)據(jù).


          十二. 使用分片數(shù)據(jù)創(chuàng)建好友動(dòng)態(tài)

          為任何給定用戶創(chuàng)建好友動(dòng)態(tài)最重要的要求之一就是從該用戶關(guān)注的所有人那里獲取最新的照片。為此,我們需要一種機(jī)制來(lái)對(duì)照片在創(chuàng)建時(shí)進(jìn)行排序。為了有效地做到這一點(diǎn),我們可以將照片創(chuàng)建時(shí)間作為PhotoID的一部分。因?yàn)槲覀冊(cè)赑hotoID上有一個(gè)主索引,所以很快就能找到最新的PhotoID。

          我們可以使用時(shí)間來(lái)記錄。假設(shè)PhotoID有兩部分,第一部分將表示epoch時(shí)間,而第二部分將是一個(gè)自動(dòng)遞增的序列。因此,要?jiǎng)?chuàng)建一個(gè)新的PhotoID時(shí),我們可以取當(dāng)前的epoch time,并從生成密鑰的DB中添加一個(gè)自動(dòng)遞增的ID。我們可以從這個(gè)PhotoID (PhotoID % 10)中計(jì)算出分片數(shù),并將照片存儲(chǔ)在那里。

          PhotoID的大小是多少? 假設(shè)我們的時(shí)間從今天開(kāi)始,我們需要多少位來(lái)存儲(chǔ)未來(lái) 50 年的秒數(shù)?

          86400 sec/day * 365 (days a year) * 50 (years) => 1.6 billion seconds

          我們需要31位來(lái)存儲(chǔ)這個(gè)數(shù)字。平均而言,我們預(yù)計(jì)每秒會(huì)有23張新照片,我們可以分配9位來(lái)存儲(chǔ)自動(dòng)遞增序列。所以每一秒我們都能存儲(chǔ)(2^9 => 512)新照片。我們可以每秒重置自動(dòng)遞增序列。

          十三. 緩存與負(fù)載均衡

          我們的服務(wù)將需要一個(gè)大規(guī)模的照片傳送系統(tǒng)來(lái)服務(wù)全球分布的用戶。我們的服務(wù)應(yīng)該使用大量地理分布的照片緩存服務(wù)器,并使用cdn(詳細(xì)信息請(qǐng)參見(jiàn)緩存),將內(nèi)容推向用戶。

          為元數(shù)據(jù)服務(wù)器引入一個(gè)緩存來(lái)緩存部分熱點(diǎn)數(shù)據(jù)。我們可以使用Memcache來(lái)緩存數(shù)據(jù),應(yīng)用服務(wù)器在訪問(wèn)數(shù)據(jù)庫(kù)之前可以快速檢查緩存中是否有所需的行。對(duì)于我們的系統(tǒng)來(lái)說(shuō),最近最少使用(LRU)是一種合理的緩存回收策略。在這個(gè)策略下,我們首先丟棄最近查看次數(shù)最少的行。

          如何構(gòu)建更智能的緩存? 如果我們采用80-20法則,即每天20%的照片閱讀量產(chǎn)生80%的流量,這些照片非常受歡迎,大多數(shù)人都會(huì)查看訪問(wèn)它們。這意味著我們可以嘗試緩存每日照片和元數(shù)據(jù)讀取量的20%。

          References

          [1] 《系統(tǒng)設(shè)計(jì)面試的萬(wàn)金油》: http://antzuhl.cn/archives/%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1%E9%9D%A2%E8%AF%95%E7%9A%84%E4%B8%87%E9%87%91%E6%B2%B9
          [2] 《系統(tǒng)設(shè)計(jì)面試的萬(wàn)金油》: http://antzuhl.cn/archives/%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1%E9%9D%A2%E8%AF%95%E7%9A%84%E4%B8%87%E9%87%91%E6%B2%B9
          [3] 系統(tǒng)設(shè)計(jì)實(shí)踐(01) - 短鏈服務(wù): http://antzuhl.cn/archives/xi-tong-she-ji-shi-jian-duan-lian-fu-wu
          [4] 系統(tǒng)設(shè)計(jì)實(shí)踐(02) - 文本存儲(chǔ)服務(wù): http://antzuhl.cn/archives/wen-ben-cun-chu-fu-wu
          [5] SQL vs NoSQL: https://www.educative.io/collection/page/5668639101419520/5649050225344512/5728116278296576/

          討論

          瀏覽 29
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  成人视频在线观看视频在线观看黄色 | 精品视频一区视频二区视频三区视频四区 | 男女h网站| 成人 自拍偷拍 | 一级黄色免费在线 |