国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

目錄
文章系列
1. 陳舊讀取
對(duì)最終用戶的影響
令人沮喪的體驗(yàn)和不公平的優(yōu)勢(shì)
陳舊讀取導(dǎo)致重複寫(xiě)入
對(duì)開(kāi)發(fā)人員的影響
表現(xiàn)出這種異常的數(shù)據(jù)庫(kù)
2. 丟失寫(xiě)入
不可預(yù)測(cè)的安全性
容易丟失寫(xiě)入的數(shù)據(jù)庫(kù)
3. 寫(xiě)入偏差
數(shù)據(jù)質(zhì)量
以不同的方式編寫(xiě)代碼以避免回滾
容易出現(xiàn)寫(xiě)入偏差的數(shù)據(jù)庫(kù)
4. 亂序?qū)懭?/a>
對(duì)話重新排序
用戶操作重新排序
漏洞
容易出現(xiàn)亂序?qū)懭氲臄?shù)據(jù)庫(kù)
所有異常都可能在一致性受限時(shí)返回
結(jié)論
首頁(yè) web前端 css教學(xué) 一致的後端和UX:怎麼了?

一致的後端和UX:怎麼了?

Apr 09, 2025 am 11:08 AM

Consistent Backends and UX: What Can Go Wrong?

文章系列

  1. 為什麼你應(yīng)該關(guān)心?
  2. 可能出現(xiàn)什麼問(wèn)題?
  3. 採(cǎi)用新技術(shù)的障礙是什麼?
  4. 新算法如何提供幫助?

上一篇文章解釋了強(qiáng)一致性(與最終一致性相對(duì))。本文是系列文章的第二部分,我們將解釋缺乏強(qiáng)一致性如何使提供良好的最終用戶體驗(yàn)變得更加困難,如何帶來(lái)嚴(yán)重的工程開(kāi)銷,以及如何使您容易受到攻擊。本部分較長(zhǎng),因?yàn)槲覀儗⒔忉尣煌臄?shù)據(jù)庫(kù)異常,並通過(guò)幾個(gè)示例場(chǎng)景,並簡(jiǎn)要介紹哪種類型的數(shù)據(jù)庫(kù)容易受到每種異常的影響。

用戶體驗(yàn)是任何應(yīng)用程序成功的驅(qū)動(dòng)因素,依賴於不一致的後端會(huì)增加提供良好體驗(yàn)的挑戰(zhàn)。更重要的是,在不一致的數(shù)據(jù)之上構(gòu)建應(yīng)用程序邏輯會(huì)導(dǎo)致漏洞。一篇論文將這類攻擊稱為“ACIDrain”。他們調(diào)查了12 個(gè)最流行的自託管電子商務(wù)應(yīng)用程序,並發(fā)現(xiàn)了至少22 種可能的嚴(yán)重攻擊。一個(gè)網(wǎng)站是比特幣錢包服務(wù),由於這些攻擊不得不關(guān)閉。當(dāng)您選擇一個(gè)不是100% ACID 的分佈式數(shù)據(jù)庫(kù)時(shí),就會(huì)有麻煩。正如我們之前的例子所解釋的那樣,由於誤解、定義不明確的術(shù)語(yǔ)和激進(jìn)的營(yíng)銷,工程師很難確定特定數(shù)據(jù)庫(kù)提供的保證。

什麼麻煩?您的應(yīng)用程序可能會(huì)出現(xiàn)諸如帳戶餘額錯(cuò)誤、用戶獎(jiǎng)勵(lì)未收到、交易執(zhí)行兩次、消息亂序或違反應(yīng)用程序規(guī)則等問(wèn)題。有關(guān)為什麼需要分佈式數(shù)據(jù)庫(kù)以及為什麼它們很困難的快速介紹,請(qǐng)參閱我們的第一篇文章或此精彩的視頻解釋。簡(jiǎn)而言之,分佈式數(shù)據(jù)庫(kù)是一個(gè)將數(shù)據(jù)的副本保存在多個(gè)位置的數(shù)據(jù)庫(kù),原因是可擴(kuò)展性、延遲和可用性。

我們將介紹這四個(gè)潛在問(wèn)題(還有更多問(wèn)題),並用遊戲開(kāi)發(fā)中的例子來(lái)說(shuō)明它們。遊戲開(kāi)發(fā)很複雜,這些開(kāi)發(fā)人員面臨許多與現(xiàn)實(shí)生活中的嚴(yán)重問(wèn)題非常相似的問(wèn)題。遊戲有交易系統(tǒng)、消息系統(tǒng)、需要滿足條件的獎(jiǎng)勵(lì)等等。記住,如果事情出錯(cuò)或看起來(lái)出錯(cuò),遊戲玩家會(huì)多么生氣(或高興?)。在遊戲中,用戶體驗(yàn)至關(guān)重要,因此遊戲開(kāi)發(fā)人員通常承受著巨大的壓力,以確保他們的系統(tǒng)具有容錯(cuò)性。

準(zhǔn)備好了嗎?讓我們深入探討第一個(gè)潛在問(wèn)題!

1. 陳舊讀取

陳舊讀取是指返回舊數(shù)據(jù)的讀取,換句話說(shuō),返回的值根據(jù)最新的寫(xiě)入尚未更新。許多分佈式數(shù)據(jù)庫(kù),包括使用副本進(jìn)行向上擴(kuò)展的傳統(tǒng)數(shù)據(jù)庫(kù)(閱讀第1 部分以了解這些數(shù)據(jù)庫(kù)的工作原理),都會(huì)出現(xiàn)陳舊讀取問(wèn)題。

對(duì)最終用戶的影響

首先,陳舊讀取會(huì)影響最終用戶。而且這不是單一的影響。

令人沮喪的體驗(yàn)和不公平的優(yōu)勢(shì)

想像一下,遊戲中兩個(gè)用戶遇到一個(gè)裝有金幣的寶箱。第一個(gè)用戶從一個(gè)數(shù)據(jù)庫(kù)服務(wù)器接收數(shù)據(jù),而第二個(gè)用戶連接到第二個(gè)數(shù)據(jù)庫(kù)服務(wù)器。事件順序如下:

  1. 用戶1(通過(guò)數(shù)據(jù)庫(kù)服務(wù)器1)看到並打開(kāi)寶箱,取走金幣。
  2. 用戶2(通過(guò)數(shù)據(jù)庫(kù)服務(wù)器2)看到一個(gè)裝滿的寶箱,打開(kāi)它,失敗了。
  3. 用戶2 仍然看到一個(gè)裝滿的寶箱,並且不明白為什麼它會(huì)失敗。

雖然這似乎是一個(gè)小問(wèn)題,但結(jié)果是第二個(gè)玩家的體驗(yàn)令人沮喪。他不僅處?kù)读觿?shì),而且還經(jīng)常會(huì)在遊戲中看到一些看起來(lái)存在但實(shí)際上不存在的情況。接下來(lái),讓我們來(lái)看一個(gè)玩家對(duì)陳舊讀取採(cǎi)取行動(dòng)的例子!

陳舊讀取導(dǎo)致重複寫(xiě)入

想像一下,遊戲中一個(gè)角色試圖在商店裡購(gòu)買盾牌和劍的情況。如果有多個(gè)位置包含數(shù)據(jù)並且沒(méi)有智能係統(tǒng)來(lái)提供一致性,則一個(gè)節(jié)點(diǎn)包含的數(shù)據(jù)將比另一個(gè)節(jié)點(diǎn)舊。在這種情況下,用戶可能會(huì)購(gòu)買物品(聯(lián)繫第一個(gè)節(jié)點(diǎn)),然後檢查他的庫(kù)存(聯(lián)繫第二個(gè)節(jié)點(diǎn)),卻發(fā)現(xiàn)物品不存在。用戶可能會(huì)感到困惑,並可能認(rèn)為交易沒(méi)有成功。在這種情況下,大多數(shù)人會(huì)怎麼做?好吧,他們會(huì)再次嘗試購(gòu)買該商品。一旦第二個(gè)節(jié)點(diǎn)趕上,用戶已經(jīng)購(gòu)買了副本,一旦副本趕上,他突然發(fā)現(xiàn)他的錢用完了,每種物品都有兩件。他認(rèn)為我們的遊戲壞了。

在這種情況下,用戶花費(fèi)了他不希望花費(fèi)的資源。如果我們?cè)谶@樣的數(shù)據(jù)庫(kù)之上編寫(xiě)電子郵件客戶端,用戶可能會(huì)嘗試發(fā)送電子郵件,然後刷新瀏覽器,但無(wú)法檢索他剛剛發(fā)送的電子郵件,因此會(huì)再次發(fā)送。在這樣的系統(tǒng)之上提供良好的用戶體驗(yàn)和實(shí)現(xiàn)安全的交易(例如銀行交易)非常困難。

對(duì)開(kāi)發(fā)人員的影響

在編碼時(shí),您總是必須預(yù)期某些東西(尚未)存在並相應(yīng)地進(jìn)行編碼。當(dāng)讀取最終一致時(shí),編寫(xiě)防故障代碼變得非常具有挑戰(zhàn)性,並且用戶很可能會(huì)在您的應(yīng)用程序中遇到問(wèn)題。當(dāng)讀取最終一致時(shí),這些問(wèn)題會(huì)在您能夠調(diào)查它們之前消失?;旧?,您最終是在追逐幽靈。開(kāi)發(fā)人員仍然經(jīng)常選擇最終一致的數(shù)據(jù)庫(kù)或分發(fā)方法,因?yàn)橥ǔP枰獣r(shí)間才能注意到問(wèn)題。然後,一旦他們的應(yīng)用程序中出現(xiàn)問(wèn)題,他們就會(huì)嘗試發(fā)揮創(chuàng)意並在其傳統(tǒng)數(shù)據(jù)庫(kù)之上構(gòu)建解決方案(1, 2) 來(lái)修復(fù)陳舊讀取。存在許多這樣的指南以及Cassandra 等數(shù)據(jù)庫(kù)已經(jīng)實(shí)現(xiàn)了一些一致性功能的事實(shí)表明,這些問(wèn)題是真實(shí)的,並且比您想像的更頻繁地在生產(chǎn)系統(tǒng)中造成問(wèn)題。在非為一致性而構(gòu)建的系統(tǒng)之上構(gòu)建的自定義解決方案非常複雜且脆弱。如果存在開(kāi)箱即用地提供強(qiáng)一致性的數(shù)據(jù)庫(kù),為什麼有人會(huì)經(jīng)歷這樣的麻煩呢?

表現(xiàn)出這種異常的數(shù)據(jù)庫(kù)

使用主讀取複製的傳統(tǒng)數(shù)據(jù)庫(kù)(PostgreSQL、MySQL、SQL Server 等)通常會(huì)出現(xiàn)陳舊讀取問(wèn)題。許多較新的分佈式數(shù)據(jù)庫(kù)也最初是最終一致的,或者換句話說(shuō),沒(méi)有針對(duì)陳舊讀取的保護(hù)。這是由於開(kāi)發(fā)人員社區(qū)中的一種強(qiáng)烈信念,即這是擴(kuò)展所必需的。最著名的數(shù)據(jù)庫(kù)就是這樣開(kāi)始的,但它認(rèn)識(shí)到其用戶如何努力處理這種異常,並且此後提供了額外的措施來(lái)避免這種情況。較舊的數(shù)據(jù)庫(kù)或未設(shè)計(jì)為高效提供強(qiáng)一致性的數(shù)據(jù)庫(kù)(如Cassandra、CouchDB 和DynamoDB)默認(rèn)情況下最終是一致的。 Riak 等其他方法最終也是一致的,但通過(guò)實(shí)現(xiàn)衝突解決系統(tǒng)來(lái)降低過(guò)時(shí)值的機(jī)率,採(cǎi)取了不同的路徑。但是,這並不能保證您的數(shù)據(jù)安全,因?yàn)樾n突解決並非萬(wàn)無(wú)一失。

2. 丟失寫(xiě)入

在分佈式數(shù)據(jù)庫(kù)領(lǐng)域,當(dāng)寫(xiě)入同時(shí)發(fā)生時(shí),需要做出一個(gè)重要的選擇。一種選擇(安全的選擇)是確保所有數(shù)據(jù)庫(kù)節(jié)點(diǎn)都能就這些寫(xiě)入的順序達(dá)成一致。這遠(yuǎn)非微不足道,因?yàn)樗葱枰綍r(shí)鐘(為此需要特定的硬件),要么需要像Calvin 這樣的不依賴於時(shí)鐘的智能算法。第二個(gè)不太安全的選擇是允許每個(gè)節(jié)點(diǎn)本地寫(xiě)入,然後稍後決定如何處理衝突。選擇第二種選擇的數(shù)據(jù)庫(kù)可能會(huì)丟失您的寫(xiě)入。

對(duì)最終用戶的影響

考慮遊戲中兩個(gè)交易,我們從11 個(gè)金幣開(kāi)始併購(gòu)買兩件物品。首先,我們以5 個(gè)金幣的價(jià)格購(gòu)買一把劍,然後以5 個(gè)金幣的價(jià)格購(gòu)買一個(gè)盾牌,並且這兩個(gè)交易都定向到我們分佈式數(shù)據(jù)庫(kù)的不同節(jié)點(diǎn)。每個(gè)節(jié)點(diǎn)讀取該值,在本例中,對(duì)於兩個(gè)節(jié)點(diǎn)來(lái)說(shuō)仍然是11。兩個(gè)節(jié)點(diǎn)都將決定寫(xiě)入6 作為結(jié)果(11-5),因?yàn)樗鼈儾恢廊魏螐?fù)制。由於第二個(gè)事務(wù)尚未看到第一個(gè)寫(xiě)入的值,因此玩家最終以總共5 個(gè)金幣的價(jià)格購(gòu)買了劍和盾牌,而不是10 個(gè)金幣。對(duì)用戶有利,但對(duì)系統(tǒng)不利!為了補(bǔ)救這種行為,分佈式數(shù)據(jù)庫(kù)有幾種策略——有些比其他策略更好。

解決策略包括“最後寫(xiě)入獲勝”(LWW)或“最長(zhǎng)版本歷史記錄”(LVH)獲勝。長(zhǎng)期以來(lái),LWW 一直是Cassandra 的策略,如果您不進(jìn)行不同的配置,它仍然是默認(rèn)行為。

如果我們將LWW 衝突解決應(yīng)用於我們之前的示例,玩家仍然剩下6 個(gè)金幣,但只會(huì)購(gòu)買一件物品。這是一種糟糕的用戶體驗(yàn),因?yàn)閼?yīng)用程序確認(rèn)了他對(duì)第二件物品的購(gòu)買,即使數(shù)據(jù)庫(kù)沒(méi)有將其識(shí)別為存在於他的庫(kù)存中。

不可預(yù)測(cè)的安全性

正如您可能想像的那樣,在這樣的系統(tǒng)之上編寫(xiě)安全規(guī)則是不安全的。許多應(yīng)用程序依賴於後端(或盡可能直接在數(shù)據(jù)庫(kù)上)的複雜安全規(guī)則來(lái)確定用戶是否可以訪問(wèn)資源。當(dāng)這些規(guī)則基於不可靠地更新的陳舊數(shù)據(jù)時(shí),我們?nèi)绾尾拍艽_保永遠(yuǎn)不會(huì)發(fā)生違規(guī)?想像一下,PaaS 應(yīng)用程序的一位用戶打電話給他的管理員並詢問(wèn):“您能否將此公共組設(shè)為私有,以便我們可以將其重新用於內(nèi)部數(shù)據(jù)?”管理員應(yīng)用該操作並告訴他已完成。但是,由於管理員和用戶可能位於不同的節(jié)點(diǎn)上,因此用戶可能會(huì)開(kāi)始將敏感數(shù)據(jù)添加到技術(shù)上仍然是公共的組中。

對(duì)開(kāi)發(fā)人員的影響

當(dāng)寫(xiě)入丟失時(shí),調(diào)試用戶問(wèn)題將是一場(chǎng)噩夢(mèng)。想像一下,用戶報(bào)告說(shuō)他在您的應(yīng)用程序中丟失了數(shù)據(jù),然後過(guò)了一天才有時(shí)間回復(fù)。您將如何嘗試找出問(wèn)題是由您的數(shù)據(jù)庫(kù)還是由有故障的應(yīng)用程序邏輯引起的?在允許跟蹤數(shù)據(jù)歷史記錄的數(shù)據(jù)庫(kù)(如FaunaDB 或Datomic)中,您可以追溯到過(guò)去以查看數(shù)據(jù)是如何被操作的。但是,這些數(shù)據(jù)庫(kù)都不會(huì)受到丟失寫(xiě)入的影響,並且確實(shí)容易受到這種異常影響的數(shù)據(jù)庫(kù)通常不具備時(shí)光倒流功能。

容易丟失寫(xiě)入的數(shù)據(jù)庫(kù)

所有使用衝突解決而不是衝突避免的數(shù)據(jù)庫(kù)都會(huì)丟失寫(xiě)入。 Cassandra 和DynamoDB 使用最後寫(xiě)入獲勝(LWW) 作為默認(rèn)值;MongoDB 曾經(jīng)使用LWW,但此後已放棄使用。傳統(tǒng)數(shù)據(jù)庫(kù)(如MySQL)中的主-主分發(fā)方法提供不同的衝突解決策略。許多未為一致性而構(gòu)建的分佈式數(shù)據(jù)庫(kù)都會(huì)丟失寫(xiě)入。 Riak 最簡(jiǎn)單的衝突解決是由LWW 驅(qū)動(dòng)的,但它們也實(shí)現(xiàn)了更智能的系統(tǒng)。但即使使用智能係統(tǒng),有時(shí)也沒(méi)有明顯的方法來(lái)解決衝突。 Riak 和CouchDB 將選擇正確寫(xiě)入的責(zé)任交給客戶端或應(yīng)用程序,允許他們手動(dòng)選擇要保留哪個(gè)版本。

由於分發(fā)很複雜,大多數(shù)數(shù)據(jù)庫(kù)都使用不完善的算法,因此當(dāng)節(jié)點(diǎn)崩潰或出現(xiàn)網(wǎng)絡(luò)分區(qū)時(shí),許多數(shù)據(jù)庫(kù)中都會(huì)經(jīng)常發(fā)生丟失寫(xiě)入。即使是MongoDB(它不分發(fā)寫(xiě)入(寫(xiě)入轉(zhuǎn)到一個(gè)節(jié)點(diǎn))),在節(jié)點(diǎn)在寫(xiě)入後立即宕機(jī)的罕見(jiàn)情況下也可能發(fā)生寫(xiě)入衝突。

3. 寫(xiě)入偏差

寫(xiě)入偏差是數(shù)據(jù)庫(kù)供應(yīng)商稱之為快照一致性的保證類型中可能發(fā)生的事情。在快照一致性中,事務(wù)從事務(wù)開(kāi)始時(shí)拍攝的快照中讀取??煺找恢滦钥梢苑乐乖S多異常。事實(shí)上,許多人認(rèn)為它是完全安全的,直到出現(xiàn)論文(PDF) 證明事實(shí)並非如此。因此,開(kāi)發(fā)人員難以理解為什麼某些保證不夠好也就不足為奇了。

在我們討論快照一致性中哪些不起作用之前,讓我們首先討論哪些起作用。假設(shè)我們有一個(gè)騎士和法師之間的戰(zhàn)鬥,他們各自的生命力由四個(gè)心組成。

當(dāng)任何角色受到攻擊時(shí),事務(wù)是一個(gè)計(jì)算已移除多少心的函數(shù):

 <code>damageCharacter(character, damage) { character.hearts = character.hearts - damage character.dead = isCharacterDead(character) }</code>

並且,在每次攻擊之後,另一個(gè)isCharacterDead 函數(shù)也會(huì)運(yùn)行以查看角色是否還有任何心:

 <code>isCharacterDead(character) { if (character.hearts </code>

在一個(gè)簡(jiǎn)單的情況下,騎士的攻擊從法師身上移除了三個(gè)心,然後法師的法術(shù)從騎士身上移除了四個(gè)心,使他自己的生命值恢復(fù)到四個(gè)。如果一個(gè)事務(wù)在另一個(gè)事務(wù)之後運(yùn)行,那麼這兩個(gè)事務(wù)在大多數(shù)數(shù)據(jù)庫(kù)中的行為將是正確的。

但是,如果我們添加第三個(gè)事務(wù),即騎士的攻擊,它與法師的法術(shù)同時(shí)運(yùn)行呢?

騎士死了嗎,法師還活著嗎?

為了處理這種混亂,快照一致性系統(tǒng)通常實(shí)現(xiàn)一個(gè)稱為“第一個(gè)提交者獲勝”的規(guī)則。只有當(dāng)另一個(gè)事務(wù)尚未寫(xiě)入同一行時(shí),事務(wù)才能結(jié)束,否則它將回滾。在這個(gè)例子中,由於兩個(gè)事務(wù)都試圖寫(xiě)入同一行(法師的健康值),只有生命吸取法術(shù)會(huì)起作用,而騎士的第二次攻擊將被回滾。然後,最終結(jié)果將與之前的示例相同:一個(gè)死去的騎士和一個(gè)擁有完整生命值的法師。

但是,MySQL 和InnoDB 等一些數(shù)據(jù)庫(kù)並不認(rèn)為“第一個(gè)提交者獲勝”是快照隔離的一部分。在這種情況下,我們將有一個(gè)丟失寫(xiě)入:法師現(xiàn)在死了,儘管他應(yīng)該在騎士的攻擊生效之前從生命吸取中獲得生命值。 (我們確實(shí)提到了定義不明確的術(shù)語(yǔ)和寬鬆的解釋,對(duì)吧?)

包含“第一個(gè)提交者獲勝”規(guī)則的快照一致性確實(shí)很好地處理了一些事情,這並不奇怪,因?yàn)樗L(zhǎng)期以來(lái)被認(rèn)為是一個(gè)很好的解決方案。這仍然是PostgreSQL、Oracle 和SQL Server 的方法,但它們都有不同的名稱。 PostgreSQL 將此保證稱為“可重複讀取”,Oracle 將其稱為“可序列化”(根據(jù)我們的定義是不正確的),而SQL Server 將其稱為“快照隔離”。難怪人們?cè)谶@個(gè)術(shù)語(yǔ)森林中迷路了。讓我們看看它沒(méi)有按預(yù)期運(yùn)行的示例!

對(duì)最終用戶的影響

接下來(lái)的戰(zhàn)鬥將發(fā)生在兩支軍隊(duì)之間,如果所有軍隊(duì)的角色都死了,則一支軍隊(duì)被認(rèn)為是死了的:

 isArmyDead(army){
  if (all characters are dead) { return true }
  else { return false }
}

在每次攻擊之後,以下函數(shù)確定角色是否死亡,然後運(yùn)行上述函數(shù)以查看軍隊(duì)是否死亡:

 damageArmyCharacter(army, character, damage){
  character.hearts = character.hearts - damage
  character.dead = isCharacterDead(character)
  armyDead = isArmyDead(army)
  if (army.dead != armyDead){
    army.dead = armyDead
  }
}

首先,角色的心臟會(huì)因受到的傷害而減少。然後,我們通過(guò)檢查每個(gè)角色是否沒(méi)有生命值來(lái)驗(yàn)證軍隊(duì)是否死亡。然後,如果軍隊(duì)的狀態(tài)發(fā)生了變化,我們將更新軍隊(duì)的“死亡”布爾值。

有三個(gè)法師分別攻擊一次,導(dǎo)致三個(gè)“生命吸取”事務(wù)??煺帐窃谑聞?wù)開(kāi)始時(shí)拍攝的,由於所有事務(wù)同時(shí)開(kāi)始,因此快照是相同的。每個(gè)事務(wù)都有一個(gè)數(shù)據(jù)副本,其中所有騎士仍然擁有完整的生命值。

讓我們看看第一個(gè)“生命吸取”事務(wù)是如何解決的。在這個(gè)事務(wù)中,mage1 攻擊knight1,騎士損失4 個(gè)生命值,而攻擊法師恢復(fù)了全部生命值。事務(wù)決定騎士軍隊(duì)沒(méi)有死亡,因?yàn)樗荒芸吹揭粋€(gè)快照,其中兩個(gè)騎士仍然擁有完整的生命值,一個(gè)騎士死了。其他兩個(gè)事務(wù)作用於另一個(gè)法師和騎士,但以類似的方式進(jìn)行。這些事務(wù)中的每一個(gè)最初在其數(shù)據(jù)副本中都有三個(gè)活著的騎士,並且只看到一個(gè)騎士死亡。因此,每個(gè)事務(wù)都決定騎士軍隊(duì)仍然活著。

當(dāng)所有事務(wù)完成後,沒(méi)有一個(gè)騎士還活著,但我們指示軍隊(duì)是否死亡的布爾值仍然設(shè)置為false。為什麼?因?yàn)樵谂臄z快照時(shí),沒(méi)有一個(gè)騎士死亡。因此,每個(gè)事務(wù)都看到自己的騎士死亡,但不知道軍隊(duì)中的其他騎士。雖然這是我們系統(tǒng)中的異常(稱為寫(xiě)入偏差),但寫(xiě)入已通過(guò),因?yàn)樗鼈兏髯詫?xiě)入不同的角色,並且對(duì)軍隊(duì)的寫(xiě)入從未改變。太棒了,我們現(xiàn)在有一支幽靈軍隊(duì)!

對(duì)開(kāi)發(fā)人員的影響

數(shù)據(jù)質(zhì)量

如果我們想確保用戶擁有唯一的名稱怎麼辦?我們創(chuàng)建用戶的事務(wù)將檢查名稱是否存在;如果不存在,我們將使用該名稱寫(xiě)入新用戶。但是,如果兩個(gè)用戶嘗試使用相同的名稱註冊(cè),快照將不會(huì)注意到任何事情,因?yàn)橛脩舯粚?xiě)入不同的行,因此不會(huì)發(fā)生衝突。我們現(xiàn)在系統(tǒng)中有兩個(gè)同名用戶。

由於寫(xiě)入偏差,可能會(huì)出現(xiàn)許多其他異常示例。如果您感興趣,Martin Kleppman 的著作《設(shè)計(jì)數(shù)據(jù)密集型應(yīng)用程序》對(duì)此進(jìn)行了更詳細(xì)的描述。

以不同的方式編寫(xiě)代碼以避免回滾

現(xiàn)在,讓我們考慮一種不同的方法,其中攻擊並非針對(duì)軍隊(duì)中的特定角色。在這種情況下,數(shù)據(jù)庫(kù)負(fù)責(zé)選擇首先應(yīng)該攻擊哪個(gè)騎士。

 damageArmy(army, damage){
  character = getFirstHealthyCharacter(knight)
  character.hearts = character.hearts - damage
  character.dead = isCharacterDead(character)
  // ...
}

如果我們像之前的示例一樣並行執(zhí)行多次攻擊,則getFirstHealthyCharacter 將始終針對(duì)相同的騎士,這將導(dǎo)致多個(gè)事務(wù)寫(xiě)入同一行。這將被“第一個(gè)提交者獲勝”規(guī)則阻止,該規(guī)則將回滾其他兩次攻擊。雖然它可以防止異常,但開(kāi)發(fā)人員需要了解這些問(wèn)題並圍繞它們創(chuàng)造性地編寫(xiě)代碼。但是,如果數(shù)據(jù)庫(kù)開(kāi)箱即用地為您做到這一點(diǎn),豈不是更容易嗎?

容易出現(xiàn)寫(xiě)入偏差的數(shù)據(jù)庫(kù)

任何提供快照隔離而不是可序列化性的數(shù)據(jù)庫(kù)都可能出現(xiàn)寫(xiě)入偏差。有關(guān)數(shù)據(jù)庫(kù)及其隔離級(jí)別的概述,請(qǐng)參閱本文。

對(duì)最終用戶的影響

對(duì)話重新排序

如果有人因錯(cuò)誤而發(fā)送第二條消息,則可以以令人困惑的方式對(duì)對(duì)話進(jìn)行排序。

用戶操作重新排序

如果我們的玩家有11 個(gè)金幣,並且只是按重要性順序購(gòu)買物品,而沒(méi)有主動(dòng)檢查他擁有的金幣數(shù)量,那麼數(shù)據(jù)庫(kù)可以重新排序這些購(gòu)買訂單。如果他沒(méi)有足夠的錢,他本可以先購(gòu)買最重要性最低的物品。

在這種情況下,有一個(gè)數(shù)據(jù)庫(kù)檢查驗(yàn)證我們是否有足夠的黃金。想像一下,我們沒(méi)有足夠的錢,讓賬戶低於零會(huì)花費(fèi)我們錢,就像銀行在您低於零時(shí)向您收取透支費(fèi)一樣。您可能會(huì)快速出售一件物品以確保您有足夠的錢購(gòu)買所有三件物品。但是,旨在增加您餘額的銷售可能會(huì)重新排序到交易列表的末尾,這將有效地將您的餘額推至零以下。如果這是一家銀行,您很可能會(huì)產(chǎn)生您絕對(duì)不應(yīng)承擔(dān)的費(fèi)用。

不可預(yù)測(cè)的安全性

在配置安全設(shè)置後,用戶會(huì)期望這些設(shè)置將應(yīng)用於所有即將執(zhí)行的操作,但是當(dāng)用戶通過(guò)不同的渠道相互交談時(shí),可能會(huì)出現(xiàn)問(wèn)題。記住我們討論過(guò)的例子,管理員正在與想要將一個(gè)組設(shè)為私有的用戶通話,然後向其中添加敏感數(shù)據(jù)。雖然在提供可序列化性的數(shù)據(jù)庫(kù)中,這種情況可能發(fā)生的時(shí)間窗口變得更小,但這仍然可能發(fā)生,因?yàn)楣芾韱T的操作可能直到用戶操作之後才能完成。當(dāng)用戶通過(guò)不同的渠道進(jìn)行溝通並期望數(shù)據(jù)庫(kù)實(shí)時(shí)排序時(shí),事情就會(huì)出錯(cuò)。

如果由於負(fù)載平衡而將用戶重定向到不同的節(jié)點(diǎn),則也會(huì)發(fā)生此異常。在這種情況下,兩個(gè)連續(xù)的操作最終位於不同的節(jié)點(diǎn)上,並且可能會(huì)重新排序。如果一個(gè)女孩將她的父母添加到一個(gè)查看權(quán)限有限的facebook 群組中,然後發(fā)布她的春假照片,那麼這些圖片仍然可能會(huì)出現(xiàn)在她父母的feed 中。

在另一個(gè)例子中,自動(dòng)交易機(jī)器人可能具有設(shè)置,例如最高購(gòu)買價(jià)格、支出限額和要關(guān)注的股票列表。如果用戶更改機(jī)器人應(yīng)該購(gòu)買的股票列表,然後更改支出限額,那麼如果這些交易被重新排序並且交易機(jī)器人已將新分配的預(yù)算用於舊股票,他將不會(huì)感到高興。

對(duì)開(kāi)發(fā)人員的影響

漏洞

一些漏洞取決於事務(wù)的潛在反轉(zhuǎn)。想像一下,遊戲玩家一旦擁有1,000 個(gè)金幣就會(huì)獲得獎(jiǎng)杯,而他非常想要這個(gè)獎(jiǎng)杯。遊戲通過(guò)將多個(gè)容器的金幣加在一起(例如他的存儲(chǔ)和他的攜帶物(他的庫(kù)存))來(lái)計(jì)算玩家有多少金幣。如果玩家在存儲(chǔ)和庫(kù)存之間快速交換金錢,他實(shí)際上可以欺騙系統(tǒng)。

在下圖中,第二個(gè)玩家充當(dāng)犯罪夥伴,以確保存儲(chǔ)和庫(kù)存之間的資金轉(zhuǎn)移發(fā)生在不同的交易中,從而增加這些交易被路由到不同節(jié)點(diǎn)的機(jī)會(huì)。現(xiàn)實(shí)世界中更嚴(yán)重的例子是使用第三方賬戶轉(zhuǎn)賬的銀行;銀行可能會(huì)錯(cuò)誤計(jì)算某人是否有資格獲得貸款,因?yàn)楦鞣N交易已被發(fā)送到不同的節(jié)點(diǎn)並且沒(méi)有足夠的時(shí)間進(jìn)行排序。

容易出現(xiàn)亂序?qū)懭氲臄?shù)據(jù)庫(kù)

任何不提供線性化的數(shù)據(jù)庫(kù)都可能出現(xiàn)寫(xiě)入偏差。有關(guān)哪些數(shù)據(jù)庫(kù)提供線性化的概述,請(qǐng)參閱本文。劇透:並不多。

所有異常都可能在一致性受限時(shí)返回

最後要討論的強(qiáng)一致性的一個(gè)放鬆是僅保證在一定的範(fàn)圍內(nèi)。典型的範(fàn)圍是數(shù)據(jù)中心區(qū)域、分區(qū)、節(jié)點(diǎn)、集合或行。如果您在對(duì)強(qiáng)一致性施加這些類型邊界的數(shù)據(jù)庫(kù)之上進(jìn)行編程,那麼您需要記住這些邊界,以避免意外地再次打開(kāi)潘多拉魔盒。

下面是一個(gè)一致性的示例,但僅保證在一個(gè)集合內(nèi)。下面的示例包含三個(gè)集合:一個(gè)用於玩家,一個(gè)用於鐵匠(即修理玩家物品的黑鐵匠),另一個(gè)用於物品。每個(gè)玩家和每個(gè)鐵匠都有一個(gè)指向物品集合中物品的id 列表。

如果您想在兩個(gè)玩家之間交易盾牌(例如,從Brecht 到Robert),那麼一切都會(huì)很好,因?yàn)槟匀辉谝粋€(gè)集合中,因此您的事務(wù)仍然在保證一致性的範(fàn)圍內(nèi)。但是,如果羅伯特的劍在鐵匠那裡進(jìn)行修理,並且他想取回它怎麼辦?然後,事務(wù)跨越兩個(gè)集合,即鐵匠的集合和玩家的集合,並且保證被取消。這種限制通常存在於MongoDB 等文檔數(shù)據(jù)庫(kù)中。然後,您需要更改編程方式以找到圍繞限制的創(chuàng)造性解決方案。例如,您可以將物品的位置編碼到物品本身。

當(dāng)然,真正的遊戲很複雜。您可能希望能夠?qū)⑽锲返袈湓诘匕迳匣驅(qū)⑺鼈兎胖迷谑袌?chǎng)上,以便物品可以由玩家擁有,但不一定在玩家的庫(kù)存中。當(dāng)事情變得更複雜時(shí),這些變通方法會(huì)顯著增加技術(shù)深度並改變您的編碼方式以保持在數(shù)據(jù)庫(kù)的保證範(fàn)圍內(nèi)。

結(jié)論

我們已經(jīng)看到了當(dāng)您的數(shù)據(jù)庫(kù)行為與預(yù)期不符時(shí)可能出現(xiàn)的不同問(wèn)題的示例。雖然有些情況乍一看似乎微不足道,但它們都會(huì)對(duì)開(kāi)發(fā)人員的生產(chǎn)力產(chǎn)生重大影響,尤其是在系統(tǒng)擴(kuò)展時(shí)。更重要的是,它們使您容易受到不可預(yù)測(cè)的安全漏洞的攻擊——這可能會(huì)對(duì)您應(yīng)用程序的聲譽(yù)造成不可挽回的損害。

我們討論了幾種一致性程度,但是現(xiàn)在我們已經(jīng)看到了這些示例,讓我們將它們放在一起:

還請(qǐng)記住,這些正確性保證中的每一個(gè)都可能帶有邊界:

最後,請(qǐng)意識(shí)到我們只提到了少數(shù)異常和一致性保證,而實(shí)際上還有更多。對(duì)於感興趣的讀者,我強(qiáng)烈推薦Martin Kleppman 的《設(shè)計(jì)數(shù)據(jù)密集型應(yīng)用程序》。

我們生活在一個(gè)我們不再需要關(guān)心的時(shí)代,只要我們選擇一個(gè)沒(méi)有限制的強(qiáng)一致性數(shù)據(jù)庫(kù)即可。由於Calvin(FaunaDB)和Spanner(Google Spanner、FoundationDB)等新方法的出現(xiàn),我們現(xiàn)在擁有多區(qū)域分佈式數(shù)據(jù)庫(kù),這些數(shù)據(jù)庫(kù)可以提供極低的延遲,並且在每種情況下都按預(yù)期運(yùn)行。那麼,為什麼您還要冒著搬起石頭砸自己的腳的風(fēng)險(xiǎn),選擇一個(gè)不提供這些保證的數(shù)據(jù)庫(kù)呢?

在本系列的下一篇文章中,我們將介紹對(duì)開(kāi)發(fā)人員體驗(yàn)的影響。為什麼很難讓開(kāi)發(fā)人員相信一致性很重要?劇透:大多數(shù)人需要親身體驗(yàn)才能看到必要性。但是請(qǐng)考慮一下:“如果出現(xiàn)錯(cuò)誤,是您的應(yīng)用程序錯(cuò)誤,還是數(shù)據(jù)錯(cuò)誤?您如何知道?”一旦數(shù)據(jù)庫(kù)的限製表現(xiàn)為錯(cuò)誤或糟糕的用戶體驗(yàn),您就需要解決數(shù)據(jù)庫(kù)的限制,這會(huì)導(dǎo)致效率低下的粘合代碼,這些代碼無(wú)法擴(kuò)展。當(dāng)然,在那時(shí),您已經(jīng)投入了大量資金,並且意識(shí)到得太晚了。

文章系列

  1. 為什麼你應(yīng)該關(guān)心?
  2. 可能出現(xiàn)什麼問(wèn)題?
  3. 採(cǎi)用新技術(shù)的障礙是什麼?
  4. 新算法如何提供幫助?

以上是一致的後端和UX:怎麼了?的詳細(xì)內(nèi)容。更多資訊請(qǐng)關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

本網(wǎng)站聲明
本文內(nèi)容由網(wǎng)友自願(yuàn)投稿,版權(quán)歸原作者所有。本站不承擔(dān)相應(yīng)的法律責(zé)任。如發(fā)現(xiàn)涉嫌抄襲或侵權(quán)的內(nèi)容,請(qǐng)聯(lián)絡(luò)admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費(fèi)脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅(qū)動(dòng)的應(yīng)用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費(fèi)的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費(fèi)的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強(qiáng)大的PHP整合開(kāi)發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺(jué)化網(wǎng)頁(yè)開(kāi)發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級(jí)程式碼編輯軟體(SublimeText3)

熱門(mén)話題

Laravel 教程
1600
29
PHP教程
1502
276
CSS教程,用於創(chuàng)建加載旋轉(zhuǎn)器和動(dòng)畫(huà) CSS教程,用於創(chuàng)建加載旋轉(zhuǎn)器和動(dòng)畫(huà) Jul 07, 2025 am 12:07 AM

創(chuàng)建CSS加載旋轉(zhuǎn)器的方法有三種:1.使用邊框的基本旋轉(zhuǎn)器,通過(guò)HTML和CSS實(shí)現(xiàn)簡(jiǎn)單動(dòng)畫(huà);2.使用多個(gè)點(diǎn)的自定義旋轉(zhuǎn)器,通過(guò)不同延遲時(shí)間實(shí)現(xiàn)跳動(dòng)效果;3.在按鈕中添加旋轉(zhuǎn)器,通過(guò)JavaScript切換類來(lái)顯示加載狀態(tài)。每種方法都強(qiáng)調(diào)了設(shè)計(jì)細(xì)節(jié)如顏色、大小、可訪問(wèn)性和性能優(yōu)化的重要性,以提升用戶體驗(yàn)。

解決CSS瀏覽器兼容性問(wèn)題和前綴 解決CSS瀏覽器兼容性問(wèn)題和前綴 Jul 07, 2025 am 01:44 AM

處理CSS瀏覽器兼容性和前綴問(wèn)題需理解瀏覽器支持差異並合理使用廠商前綴。 1.了解常見(jiàn)問(wèn)題如Flexbox、Grid支持不一,position:sticky失效,動(dòng)畫(huà)表現(xiàn)不同;2.查閱CanIuse確認(rèn)特性支持情況;3.正確使用-webkit-、-moz-、-ms-、-o-等廠商前綴;4.推薦使用Autoprefixer自動(dòng)添加前綴;5.安裝PostCSS並配置browserslist指定目標(biāo)瀏覽器;6.構(gòu)建時(shí)自動(dòng)處理兼容性;7.老項(xiàng)目可用Modernizr檢測(cè)特性;8.不必追求所有瀏覽器一致,確

顯示:內(nèi)聯(lián),顯示:塊和顯示:內(nèi)聯(lián)塊之間有什麼區(qū)別? 顯示:內(nèi)聯(lián),顯示:塊和顯示:內(nèi)聯(lián)塊之間有什麼區(qū)別? Jul 11, 2025 am 03:25 AM

Themaindifferencesbetweendisplay:inline,block,andinline-blockinHTML/CSSarelayoutbehavior,spaceusage,andstylingcontrol.1.Inlineelementsflowwithtext,don’tstartonnewlines,ignorewidth/height,andonlyapplyhorizo????ntalpadding/margins—idealforinlinetextstyling

造型與CSS不同訪問(wèn)的鏈接 造型與CSS不同訪問(wèn)的鏈接 Jul 11, 2025 am 03:26 AM

設(shè)置訪問(wèn)過(guò)鏈接的樣式能提升用戶體驗(yàn),尤其在內(nèi)容密集型網(wǎng)站中幫助用戶更好導(dǎo)航。 1.使用CSS的:visited偽類可定義已訪問(wèn)鏈接樣式,如顏色變化;2.注意瀏覽器出於隱私限制僅允許修改部分屬性;3.顏色選擇應(yīng)與整體風(fēng)格協(xié)調(diào),避免突兀;4.移動(dòng)端可能不顯示該效果,建議結(jié)合其他視覺(jué)提示如icon輔助標(biāo)識(shí)。

使用CSS剪輯路徑創(chuàng)建自定義形狀 使用CSS剪輯路徑創(chuàng)建自定義形狀 Jul 09, 2025 am 01:29 AM

使用CSS的clip-path屬性可以裁剪元素為自定義形狀,如三角形、圓形缺口、多邊形等,無(wú)需依賴圖片或SVG。其優(yōu)勢(shì)包括:1.支持circle、ellipse、polygon等多種基本形狀;2.可響應(yīng)式調(diào)整,適配移動(dòng)端;3.易於動(dòng)畫(huà)化,可結(jié)合hover或JavaScript實(shí)現(xiàn)動(dòng)態(tài)效果;4.不影響佈局流,僅裁剪顯示區(qū)域。常見(jiàn)用法如圓形裁剪clip-path:circle(50pxatcenter)和三角形裁剪clip-path:polygon(50%0%,1000%,00%)。注意

如何使用CSS創(chuàng)建響應(yīng)式圖像? 如何使用CSS創(chuàng)建響應(yīng)式圖像? Jul 15, 2025 am 01:10 AM

要使用CSS創(chuàng)建響應(yīng)式圖片,主要可通過(guò)以下方法實(shí)現(xiàn):1.使用max-width:100%和height:auto讓圖片在保持比例的同時(shí)自適應(yīng)容器寬度;2.結(jié)合HTML的srcset和sizes屬性智能加載適配不同屏幕的圖片源;3.利用object-fit和object-position控製圖片裁剪與焦點(diǎn)展示。這些方法共同確保圖片在不同設(shè)備上清晰、美觀地呈現(xiàn)。

揭開(kāi)CSS單元的神秘面紗:PX,EM,REM,VW,VH比較 揭開(kāi)CSS單元的神秘面紗:PX,EM,REM,VW,VH比較 Jul 08, 2025 am 02:16 AM

CSS單位的選擇取決於設(shè)計(jì)需求和響應(yīng)式要求。 1.px用於固定尺寸,適合精確控制但缺乏彈性;2.em是相對(duì)單位,受父元素影響易導(dǎo)致級(jí)聯(lián)問(wèn)題,rem則基於根元素更穩(wěn)定,適合全局縮放;3.vw/vh基於視口大小,適合響應(yīng)式設(shè)計(jì),但需注意極端屏幕下的表現(xiàn);4.選擇時(shí)應(yīng)根據(jù)是否需要響應(yīng)式調(diào)整、元素層級(jí)關(guān)係及視口依賴程度來(lái)決定,合理搭配使用可提升佈局靈活性與維護(hù)性。

什麼是常見(jiàn)的CSS瀏覽器不一致? 什麼是常見(jiàn)的CSS瀏覽器不一致? Jul 26, 2025 am 07:04 AM

不同瀏覽器對(duì)CSS解析存在差異,導(dǎo)致顯示效果不一致,主要包括默認(rèn)樣式差異、盒模型計(jì)算方式、Flexbox和Grid佈局支持程度及某些CSS屬性行為不一致。 1.默認(rèn)樣式處理不一致,解決方法是使用CSSReset或Normalize.css統(tǒng)一初始樣式;2.舊版IE的盒模型計(jì)算方式不同,建議統(tǒng)一使用box-sizing:border-box;3.Flexbox和Grid在邊緣情況或舊版本中表現(xiàn)有差異,應(yīng)多測(cè)試並使用Autoprefixer;4.某些CSS屬性行為不一致,需查閱CanIuse並提供降級(jí)

See all articles