作者丨Leonardo Creed
編譯丨諾亞
出品 | 51CTO技術(shù)棧(微信號(hào):blog51cto)
在過(guò)去的幾個(gè)月里,我寫(xiě)了關(guān)于大型科技公司的各種技術(shù)“幕后揭秘”的文章,例如 Meta 的內(nèi)部無(wú)服務(wù)器平臺(tái)、 Google 內(nèi)部喜愛(ài)的代碼審查工具等等。不過(guò),蘋(píng)果的基礎(chǔ)設(shè)施并不那么公開(kāi)。我想了解 Apple 是如何構(gòu)建 iCloud 的,在這篇文章中,我將介紹我所知道的一切。
Apple 將 FoundationDB 和 Cassandra 用于其云端后端服務(wù) iCloud 和 CloudKit。而且本文的標(biāo)題并沒(méi)有弄錯(cuò):蘋(píng)果確實(shí)在其極端的多租戶架構(gòu)中存儲(chǔ)了數(shù)十億個(gè)數(shù)據(jù)庫(kù)。
一、閱讀指南
我發(fā)現(xiàn),論文中以及蘋(píng)果的實(shí)踐經(jīng)驗(yàn)與Meta無(wú)服務(wù)器平臺(tái)架構(gòu)的設(shè)計(jì)原則和教訓(xùn)高度契合。
1、兩者都巧妙地運(yùn)用了異步處理技術(shù),以實(shí)現(xiàn)用戶功能的流暢性。Meta在其無(wú)服務(wù)器架構(gòu)中,將非面向用戶的函數(shù)任務(wù)利用該技術(shù)進(jìn)行處理,從而避免影響用戶體驗(yàn)。而蘋(píng)果則在Record Layer(在下文將詳細(xì)解釋)的幾乎全部功能上采用異步處理方式,目的是隱藏延遲,確保用戶感受到的是即時(shí)響應(yīng)。
2、兩者都廣泛采用無(wú)狀態(tài)架構(gòu)設(shè)計(jì),鑒于它們都有極高的可擴(kuò)展性需求。(注:無(wú)狀態(tài)架構(gòu)意味著服務(wù)器不保存任何會(huì)話或請(qǐng)求之間的持久化狀態(tài)信息,從而使得每個(gè)請(qǐng)求都能獨(dú)立處理,且可以根據(jù)需要輕松地增加或減少服務(wù)器實(shí)例以應(yīng)對(duì)流量變化。)
3、兩者都通過(guò)邏輯隔離資源來(lái)確??煽啃院涂捎眯?。
4、兩者都以簡(jiǎn)化的方式處理各類需求。蘋(píng)果提到,為存儲(chǔ)“小數(shù)據(jù)”和“大數(shù)據(jù)”分別配置和運(yùn)營(yíng)獨(dú)立系統(tǒng)是很有誘惑力的做法,但這會(huì)增加運(yùn)維的復(fù)雜性。因此,蘋(píng)果選擇用一個(gè)抽象層來(lái)處理所有類型的數(shù)據(jù)需求。同樣地,Meta在他們的無(wú)服務(wù)器平臺(tái)上也采用相同策略,提供了一個(gè)統(tǒng)一的抽象層,用于處理各種函數(shù)負(fù)載。
5、兩者都通過(guò)構(gòu)建抽象層來(lái)優(yōu)化開(kāi)發(fā)者體驗(yàn),讓?xiě)?yīng)用開(kāi)發(fā)者無(wú)需過(guò)多關(guān)注可擴(kuò)展性需求。這些需求由底層分布式系統(tǒng)工程師在更深層次的架構(gòu)中處理。
6、深知用戶需求。無(wú)論是Meta還是Apple,它們提供的每一層架構(gòu)、API設(shè)計(jì)以及每一個(gè)設(shè)計(jì)決策都是基于對(duì)特定技術(shù)使用者(無(wú)論是應(yīng)用開(kāi)發(fā)團(tuán)隊(duì)還是可觀測(cè)性團(tuán)隊(duì))清晰理解的基礎(chǔ)上制定的。
二、Cassandra
Cassandra 是一種分布式、寬列式NoSQL數(shù)據(jù)庫(kù)管理系統(tǒng),最初由Facebook開(kāi)發(fā),用于支持Facebook收件箱搜索功能的實(shí)現(xiàn)。有趣的是,后來(lái)的Meta自身已逐步用ZippyDB替代了大量原本使用Cassandra的地方。
根據(jù)DataStax的信息,iCloud的部分功能由Cassandra提供支持。蘋(píng)果運(yùn)營(yíng)著全球規(guī)模最大的Cassandra部署之一。
他們報(bào)告指出:
- 超過(guò)30萬(wàn)個(gè)實(shí)例/節(jié)點(diǎn)
- 數(shù)據(jù)規(guī)模達(dá)到數(shù)百PB(甚至EB級(jí)別)
- 每個(gè)集群處理超過(guò)2 PB的數(shù)據(jù),且擁有數(shù)千個(gè)這樣的集群
- 每秒處理數(shù)百萬(wàn)次查詢
- 支持?jǐn)?shù)千個(gè)應(yīng)用程序
Cassandra在iCloud中的應(yīng)用確實(shí)彰顯了其管理海量數(shù)據(jù)的能力,達(dá)到EB級(jí)別。蘋(píng)果在其服務(wù)器上采用多節(jié)點(diǎn)Cassandra部署策略,并且團(tuán)隊(duì)在設(shè)計(jì)時(shí)非常注重“爆炸半徑”(blast radius)控制和數(shù)據(jù)分片(sharding),以最大程度地減少故障影響范圍并優(yōu)化數(shù)據(jù)分布與訪問(wèn)性能,從而確保iCloud服務(wù)的數(shù)據(jù)可用性接近100%。
與此同時(shí),蘋(píng)果公司內(nèi)部仍在積極改進(jìn)Cassandra技術(shù)。來(lái)自蘋(píng)果公司的Scott Andreas最近發(fā)表了關(guān)于Cassandra未來(lái)發(fā)展的演講。同時(shí),在蘋(píng)果的招聘頁(yè)面上,經(jīng)??梢钥吹剿麄?yōu)榉植际较到y(tǒng)工程師崗位列出熟練使用Cassandra的要求。
盡管Cassandra在處理大規(guī)模分布式存儲(chǔ)方面表現(xiàn)出色,但在蘋(píng)果iCloud的特定場(chǎng)景下,結(jié)合使用CloudKit和Cassandra時(shí)遇到了兩個(gè)關(guān)鍵的可擴(kuò)展性限制,這導(dǎo)致他們采用了 FoundationDB。
1、在Cassandra單一分區(qū)內(nèi),即使編輯的是不同的記錄,同一時(shí)間也只能進(jìn)行一個(gè)操作。這意味著對(duì)于那些需要多個(gè)用戶或設(shè)備同時(shí)處理共享數(shù)據(jù)的應(yīng)用程序來(lái)說(shuō),可能會(huì)出現(xiàn)性能瓶頸和并發(fā)控制問(wèn)題。
2、在Cassandra中,如果需要在一個(gè)原子操作內(nèi)同時(shí)更新多個(gè)記錄,這些更新操作會(huì)受限于單個(gè)Cassandra分區(qū)。每個(gè)分區(qū)都有其能夠處理的最大數(shù)據(jù)量限制,隨著分區(qū)內(nèi)數(shù)據(jù)的不斷增長(zhǎng),Cassandra的性能往往會(huì)隨之下降。
FoundationDB 和 Record Layer 解決了這兩個(gè)問(wèn)題。
三、FoundationDB
蘋(píng)果對(duì)FoundationDB的公開(kāi)程度要高得多。他們于 2015 年收購(gòu)了 FoundationDB,此后發(fā)表了多篇論文,詳細(xì)介紹了他們對(duì) FoundationDB 的使用。
FoundationDB 是一個(gè)開(kāi)源的分布式事務(wù)型鍵值存儲(chǔ)系統(tǒng),旨在處理大規(guī)模的數(shù)據(jù)量,并且在讀寫(xiě)混合負(fù)載以及寫(xiě)入密集型工作負(fù)載方面表現(xiàn)出色。此外,F(xiàn)oundationDB 也符合 ACID(原子性、一致性、隔離性和持久性)原則。
蘋(píng)果在CloudKit(其云端后端服務(wù))中廣泛使用了FoundationDB Record Layer。
來(lái)源:《FoundationDB Record Layer:開(kāi)源結(jié)構(gòu)化存儲(chǔ)》
從GitHub上的描述來(lái)看,Record Layer是一個(gè)基于FoundationDB的Java API,它提供了一種面向記錄的存儲(chǔ)方式,可以大致類比為一個(gè)簡(jiǎn)單的關(guān)系型數(shù)據(jù)庫(kù)。具體特性包括:
1、結(jié)構(gòu)化類型:記錄以Protocol Buffer(protobuf)消息的形式進(jìn)行定義和存儲(chǔ),Protocol Buffer是一種最初由Google設(shè)計(jì)的數(shù)據(jù)序列化協(xié)議。
2、索引:Record Layer支持多種索引類型,如值索引(大多數(shù)數(shù)據(jù)庫(kù)都提供的那種)、排名索引和聚合索引。索引和主鍵可以通過(guò)protobuf選項(xiàng)或程序化方式來(lái)定義。
3、復(fù)雜類型:支持復(fù)雜數(shù)據(jù)類型,例如列表和嵌套記錄,并且能夠針對(duì)這些嵌套結(jié)構(gòu)定義索引。
4、查詢功能:雖然Record Layer并未提供查詢語(yǔ)言,但它提供了API接口,支持對(duì)一個(gè)或多個(gè)記錄類型進(jìn)行掃描、過(guò)濾和排序操作,同時(shí)還包含一個(gè)能夠自動(dòng)選擇合適索引的查詢規(guī)劃器。
5、多個(gè)記錄存儲(chǔ)與共享模式:Record Layer允許創(chuàng)建并管理多個(gè)獨(dú)立的記錄存儲(chǔ)實(shí)例,所有實(shí)例都采用共享(且可動(dòng)態(tài)演變)的模式。舉例來(lái)說(shuō),不同于在一個(gè)單一數(shù)據(jù)庫(kù)中存儲(chǔ)所有用戶數(shù)據(jù)的方式,每個(gè)用戶可以擁有自己的記錄存儲(chǔ),甚至可以根據(jù)需要跨不同的FDB集群實(shí)例進(jìn)行分片處理。
6、極輕量級(jí):Record Layer被設(shè)計(jì)用于大型、分布式、無(wú)狀態(tài)環(huán)境,旨在實(shí)現(xiàn)從打開(kāi)存儲(chǔ)到執(zhí)行首次查詢之間的時(shí)間間隔達(dá)到毫秒級(jí)別。
7、擴(kuò)展性強(qiáng):新的索引類型以及自定義索引鍵表達(dá)式可以動(dòng)態(tài)地融入到記錄存儲(chǔ)中。
根據(jù)FoundationDB Record Layer論文所述,蘋(píng)果使用FoundationDB Record Layer為服務(wù)數(shù)億用戶的大型應(yīng)用提供強(qiáng)大的抽象層支持。CloudKit 使用Record Layer來(lái)托管數(shù)十億個(gè)獨(dú)立的數(shù)據(jù)庫(kù),其中許多數(shù)據(jù)庫(kù)共享相同的模式(schema)。
四、為什么要使用 FoundationDB Record Layer
FoundationDB、Record Layer 和 CloudKit 的結(jié)構(gòu)如下所示:
來(lái)源:《FoundationDB Record Layer: 開(kāi)源結(jié)構(gòu)化存儲(chǔ)》
- FoundationDB 負(fù)責(zé)所有的分布式系統(tǒng)和并發(fā)控制工作。
- Record Layer 作為中間層,充當(dāng)了關(guān)系數(shù)據(jù)庫(kù),以便開(kāi)發(fā)者能夠更輕松地與 FoundationDB 進(jìn)行交互。
- CloudKit 是最頂層的服務(wù),為應(yīng)用開(kāi)發(fā)者提供了豐富的功能和API。雖然CloudKit是構(gòu)建在Record Layer之上的一個(gè)典型應(yīng)用案例,但內(nèi)部還有其他服務(wù)和組件也基于Record Layer構(gòu)建,比如用于處理JSON文檔存儲(chǔ)等需要結(jié)構(gòu)化存儲(chǔ)的場(chǎng)景。
Record Layer 使蘋(píng)果能夠在大規(guī)模上實(shí)現(xiàn)多租戶支持。
實(shí)際上,這樣的描述可能還顯得保守了。
Record Layer 被用于極端的多租戶環(huán)境,其中每個(gè)應(yīng)用程序的每個(gè)用戶都能獲得獨(dú)立的記錄存儲(chǔ)空間。這意味著Record Layer 托管著數(shù)十億個(gè)共享數(shù)千種模式的獨(dú)立數(shù)據(jù)庫(kù)。
來(lái)源:《FoundationDB Record Layer: 開(kāi)源結(jié)構(gòu)化存儲(chǔ)》
Record Layer 能夠在如此大規(guī)模上成功處理多租戶問(wèn)題,主要?dú)w功于其兩個(gè)核心架構(gòu)決策:
1、無(wú)狀態(tài)操作:Record Layer 設(shè)計(jì)為無(wú)狀態(tài)模式,這意味著通過(guò)簡(jiǎn)單地增加更多無(wú)狀態(tài)實(shí)例,就可以輕松擴(kuò)展計(jì)算資源。
這種設(shè)計(jì)使得負(fù)載均衡器和路由器的工作變得更為簡(jiǎn)化,它們只需關(guān)注數(shù)據(jù)的位置而非計(jì)算服務(wù)器的具體能力。同時(shí),由于無(wú)狀態(tài)服務(wù)器無(wú)需維護(hù)會(huì)話狀態(tài)等信息,因此分配給客戶端的資源集合得以減少。
2、記錄存儲(chǔ)抽象化管理:Record Layer 使用記錄存儲(chǔ)抽象層來(lái)高效管理資源分配和可擴(kuò)展性。這個(gè)抽象層代表了整個(gè)邏輯數(shù)據(jù)庫(kù),包含了序列化數(shù)據(jù)、索引以及運(yùn)行時(shí)狀態(tài)。
每個(gè)記錄存儲(chǔ)都有特定的鍵范圍分配,確保不同租戶的數(shù)據(jù)在邏輯上保持分離。如有必要遷移某個(gè)租戶的數(shù)據(jù),過(guò)程十分直接,只需將分配給該租戶的鍵范圍遷移到新的集群中即可,因?yàn)楣芾砼c使用該記錄存儲(chǔ)所需的所有信息都包含在這個(gè)鍵范圍內(nèi)。
五、CloudKit 如何使用 FoundationDB 和Record Layer
來(lái)源:《FoundationDB Record Layer: 多租戶結(jié)構(gòu)化數(shù)據(jù)存儲(chǔ)系統(tǒng)》
在CloudKit中,每個(gè)應(yīng)用程序由一個(gè)遵循特定模式的“邏輯容器”來(lái)表示。這個(gè)模式詳細(xì)定義了必要的記錄類型、字段和索引,以實(shí)現(xiàn)高效的數(shù)據(jù)檢索和查詢功能。應(yīng)用程序在CloudKit內(nèi)部將其數(shù)據(jù)組織到不同的“區(qū)域”(zones)中,這樣可以按邏輯分組記錄,便于與客戶端設(shè)備進(jìn)行選擇性同步。
對(duì)于每一位用戶,CloudKit在FoundationDB中分配一個(gè)唯一的子空間。在這個(gè)子空間內(nèi),針對(duì)用戶使用的所有應(yīng)用程序,CloudKit都會(huì)為每個(gè)應(yīng)用創(chuàng)建一個(gè)記錄存儲(chǔ)。換言之,CloudKit實(shí)際上管理著大量邏輯數(shù)據(jù)庫(kù)——即用戶數(shù)量乘以應(yīng)用程序數(shù)量所得到的數(shù)量級(jí),每一個(gè)都包含其自身的記錄集、索引和元數(shù)據(jù),總量高達(dá)數(shù)十億個(gè)獨(dú)立數(shù)據(jù)庫(kù)。
當(dāng)CloudKit接收到來(lái)自客戶端設(shè)備的請(qǐng)求時(shí),它會(huì)通過(guò)負(fù)載均衡機(jī)制將請(qǐng)求導(dǎo)向可用的CloudKit服務(wù)進(jìn)程。該服務(wù)進(jìn)程隨后與Record Layer中的相應(yīng)記錄存儲(chǔ)進(jìn)行交互,以完成請(qǐng)求操作。
CloudKit將定義好的應(yīng)用程序模式轉(zhuǎn)換為Record Layer中的元數(shù)據(jù)定義,并將其存儲(chǔ)在獨(dú)立的元數(shù)據(jù)存儲(chǔ)中。此外,CloudKit還會(huì)添加特定的系統(tǒng)字段來(lái)豐富這些元數(shù)據(jù),如記錄的創(chuàng)建時(shí)間、修改時(shí)間以及記錄所在的區(qū)域信息。為了實(shí)現(xiàn)對(duì)每個(gè)區(qū)域內(nèi)記錄的有效訪問(wèn),區(qū)域名稱會(huì)被作為前綴附加到主鍵上。除了用戶自定義的索引外,CloudKit還管理“系統(tǒng)索引”,例如為了管理存儲(chǔ)配額而維護(hù)的一種根據(jù)記錄類型追蹤其大小的索引。
FoundationDB和Record Layer結(jié)合使用,共同解決了蘋(píng)果面臨的一些關(guān)鍵問(wèn)題,這些問(wèn)題單靠Cassandra或FoundationDB都無(wú)法完美解決。
六、已解決的問(wèn)題
1、個(gè)性化全文搜索
FoundationDB在解決用戶個(gè)性化全文搜索,以快速訪問(wèn)其數(shù)據(jù)方面發(fā)揮了重要作用。蘋(píng)果的系統(tǒng)利用了FoundationDB的鍵順序特性,能夠?qū)崿F(xiàn)對(duì)文本開(kāi)頭(前綴匹配)進(jìn)行快速搜索,并且無(wú)需額外開(kāi)銷即可處理更復(fù)雜的搜索需求,如查找相近詞或特定順序排列的詞語(yǔ)(鄰近搜索和短語(yǔ)搜索)。
在傳統(tǒng)的搜索系統(tǒng)中,通常需要后臺(tái)運(yùn)行額外的進(jìn)程來(lái)保持搜索索引的實(shí)時(shí)更新。而蘋(píng)果的系統(tǒng)則實(shí)現(xiàn)了所有操作的實(shí)時(shí)性,這意味著一旦數(shù)據(jù)發(fā)生變化,搜索索引會(huì)立即得到更新,無(wú)需任何額外步驟。這種設(shè)計(jì)不僅提高了搜索效率,還確保了數(shù)據(jù)的一致性和時(shí)效性,為用戶提供更為流暢、準(zhǔn)確的搜索體驗(yàn)。
2、高并發(fā)區(qū)域
FoundationDB為CloudKit處理同時(shí)發(fā)生的大量更新提供了更為平滑和一致的方式。
在以前使用Cassandra時(shí),CloudKit依賴于一個(gè)特殊的索引來(lái)追蹤各個(gè)區(qū)域內(nèi)的數(shù)據(jù)變化以實(shí)現(xiàn)跨設(shè)備同步。當(dāng)設(shè)備需要更新數(shù)據(jù)時(shí),會(huì)通過(guò)檢查這個(gè)索引來(lái)獲取最新信息。但這種方法存在一個(gè)問(wèn)題:當(dāng)多臺(tái)設(shè)備幾乎同時(shí)進(jìn)行更新操作時(shí),可能會(huì)引發(fā)沖突。
而采用FoundationDB后,CloudKit利用了一種特殊類型的索引,它可以精確地跟蹤每一次更改的順序,而且不會(huì)導(dǎo)致沖突。這種機(jī)制是通過(guò)為每次變更分配一個(gè)唯一的“版本號(hào)”來(lái)實(shí)現(xiàn)的,當(dāng)CloudKit需要進(jìn)行同步時(shí),它會(huì)根據(jù)這些版本號(hào)來(lái)確定設(shè)備錯(cuò)過(guò)了哪些更新內(nèi)容。
然而,在將數(shù)據(jù)從一個(gè)存儲(chǔ)集群轉(zhuǎn)移到另一個(gè)存儲(chǔ)集群(可能是為了更均勻地分布負(fù)載)時(shí),情況變得復(fù)雜起來(lái),因?yàn)槊總€(gè)集群都有自己獨(dú)立的、不匹配的版本號(hào)。為解決這一問(wèn)題,CloudKit為每位用戶的每份數(shù)據(jù)賦予了一個(gè)稱為“化身”的“遷移計(jì)數(shù)”,每當(dāng)用戶的數(shù)據(jù)被遷移到新集群時(shí),“化身”值就會(huì)遞增。每個(gè)記錄更新都會(huì)包含用戶當(dāng)前的“化身”號(hào)碼,從而確保即使在遷移之后,CloudKit仍可以根據(jù)化身號(hào)和版本號(hào)來(lái)正確判斷出更新的順序。
當(dāng)CloudKit切換到這個(gè)新系統(tǒng)時(shí),面臨的挑戰(zhàn)之一是如何處理那些尚未帶有版本號(hào)的老數(shù)據(jù)。他們巧妙地解決了這個(gè)問(wèn)題,通過(guò)運(yùn)用一種特殊函數(shù),該函數(shù)可以先按照舊系統(tǒng)的方式對(duì)老的更新進(jìn)行排序,然后再加入新系統(tǒng)的更新。這意味著無(wú)需對(duì)應(yīng)用程序進(jìn)行復(fù)雜的改動(dòng)或遺留過(guò)時(shí)代碼。此函數(shù)綜合考慮了化身、版本以及舊的更新計(jì)數(shù)器值,確保了記錄順序的準(zhǔn)確性。
3、高延遲查詢
FoundationDB 是為高并發(fā)設(shè)計(jì)的,而非針對(duì)低延遲。這意味著它能夠同時(shí)處理大量任務(wù),而不是專注于單個(gè)任務(wù)的速度。
來(lái)源:《FoundationDB Record Layer: 開(kāi)源結(jié)構(gòu)化存儲(chǔ)》
為了充分利用這種設(shè)計(jì),Record Layer在處理任務(wù)時(shí)采用了大量的異步操作方式——它會(huì)將任務(wù)排隊(duì)等待未來(lái)完成,期間可以繼續(xù)進(jìn)行其他工作。這種方法有助于掩蓋這些任務(wù)執(zhí)行過(guò)程中可能出現(xiàn)的延遲。
然而,F(xiàn)oundationDB用于與數(shù)據(jù)庫(kù)通信的工具最初是采用單線程模式設(shè)計(jì),一次只做一件事并使用一個(gè)網(wǎng)絡(luò)線程。在早期版本中,這種設(shè)置導(dǎo)致了系統(tǒng)內(nèi)部的擁堵,因?yàn)樗腥蝿?wù)都在等待輪到自己在這條網(wǎng)絡(luò)線程上執(zhí)行。Record Layer也沿用了這種單線程處理方法,這導(dǎo)致了性能瓶頸。
為了解決這一問(wèn)題,蘋(píng)果公司著手減輕這條網(wǎng)絡(luò)線程的工作負(fù)載?,F(xiàn)在,通過(guò)讓系統(tǒng)同時(shí)從多個(gè)角度與數(shù)據(jù)庫(kù)協(xié)同工作,而非形成單一的任務(wù)隊(duì)列,使得復(fù)雜的任務(wù)看上去執(zhí)行速度更快。這樣一來(lái),由于系統(tǒng)無(wú)需等待一個(gè)任務(wù)完成后再開(kāi)始另一個(gè)任務(wù),所以延遲或所謂的“緩慢感”被有效地隱藏起來(lái)。
4、沖突事務(wù)
在FoundationDB中,如果一個(gè)事務(wù)正在讀取某些鍵值,而另一個(gè)事務(wù)在同一時(shí)刻修改了這些相同的鍵值,則會(huì)導(dǎo)致“事務(wù)沖突”。FoundationDB通過(guò)提供對(duì)可能導(dǎo)致沖突的鍵集合進(jìn)行精確控制的能力,從而允許精細(xì)管理這些沖突。
避免不必要的沖突的一個(gè)常見(jiàn)方法是對(duì)一組鍵執(zhí)行一種特殊的、不會(huì)引發(fā)沖突的讀取操作,即所謂的“快照”讀取。如果這種讀取發(fā)現(xiàn)重要鍵值,那么事務(wù)只會(huì)針對(duì)那些特定鍵標(biāo)記潛在沖突,而不是整個(gè)鍵范圍。這樣可以確保事務(wù)只受到與其結(jié)果真正相關(guān)的更改影響。
Record Layer采用了這一策略來(lái)高效地管理其排名索引系統(tǒng)中的一部分結(jié)構(gòu)——跳表(skip list)。然而,手動(dòng)設(shè)置這些沖突范圍可能較為復(fù)雜,并且可能導(dǎo)致難以識(shí)別的錯(cuò)誤,特別是當(dāng)它們與應(yīng)用程序的主要邏輯混合在一起時(shí)。因此,建議構(gòu)建于FoundationDB之上的系統(tǒng)創(chuàng)建更高級(jí)別的工具,如自定義索引,以處理這些模式。這種方法有助于避免將放寬沖突規(guī)則的責(zé)任留給每個(gè)客戶端應(yīng)用,否則可能會(huì)導(dǎo)致錯(cuò)誤和一致性問(wèn)題的發(fā)生。
參考鏈接:
https://read.engineerscodex.com/p/how-apple-built-icloud-to-store-billions