国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

實戰經驗丨如何避免云服務數據不同步?

shmily / 2139人閱讀

摘要:這里有點像的主從同步一樣,拿到內存的最后版本后還有新過來的寫操作進入和隊列,先把歷史版本推給客戶端,再把之后的寫操作一次推給客戶端。

本文是野狗科技聯合創始人&架構師謝喬在ArchSummit 北京2015全球架構師峰會上進行的《基于數據同步云服務架構實踐》的演講實錄,主要分為三個方面:野狗的數據同步理念,數據同步的架構演進,數據同步的細節問題。
野狗官博:https://blog.wilddog.com/
野狗官網:https://www.wilddog.com/
公眾訂閱號:wilddogbaas

以下為演講實錄:

可能大家在實際的應用場景中不使用數據同步的業務模式,但是我是想跟大家分享我們在演進過程中一些問題的解決思路,希望能對大家有所幫助。

今天的演講內容主要分三個議題:

野狗的數據同步理念

數據同步的架構演進

數據同步的細節問題

野狗的數據同步理念

首先從云端這塊兒開始講起,我們的數據存儲是個Schema-free的形式,樹形的數據庫像一顆Json樹,更像前端工程師們用的數據結構,它能把原來的關系型數據通過一些關聯查詢形成聚合型的數據,比如blog,里面有標題、回復等內容,就相當于把數據重新聚合,這樣數據之間的關系就更直觀了,方便大家快速的設計比較好的數據結構,完美的與url結合,每條數據都通過url來唯一定位,每個path作為一個key,就成為了key-value的數據結構。

經典的云服務是這樣的:現提供一個API,然后有其他的auth接入,云端有存儲,有用戶管理,有hosting功能,還有周邊的一些工具,客戶端通過rest api這種方式與云端進行交互來開發你的業務模型。

而野狗除了這一部分以外,還有一個富客戶端的SDK,本地也做了存儲,當本地數據發生變化的時候會通過一個事件來通知用戶,然后用戶進行修改。

具體來講,是客戶端與服務端建立一個長連接,來完成數據同步,當同步完成之后產生數據變化,就可以完成業務邏輯的實現。如果我們把模型再抽象一點,就像一個主從的同步,客戶端作為從,和云端進行副本級的同步過程。

也可以有另外一種同步方式,大家的服務可以與野狗云進行實時同步。比如說,你的服務端進行了一次數據修改,同步到云端,云端把這個修改同步給關注這個數據的客戶端。

數據實現同步的基本模型是這樣的:

開始有一個初始化的慢同步,可以做全量的同步或者條件同步,比如這個例子,客戶端A進行了條件同步,同步到本地產生了一個本地副本,客戶端B通過全同步拉取到本地形成一個本地副本。當客戶端A修改后,產生了新的數據,我們把它叫增量同步,數據會push到云端。然后本地使用best-effort模式,客戶端先成功觸發事件,然后再同步到云端,云端再同步到其他的客戶端,實現最終一致性。

這個過程很像op log的過程,也是基于長連接的,如果每次連接發生了異常,這里會重新連接進行一次初始化慢同步過程。這也是我們所做的數據同步和消息推送的根本區別,原因是,消息推送要保證每個消息順序到達,而且不丟失,數據同步則是在性能上的提升,只關心最終的數據狀態。一旦發生異常,客戶端重新連入到云端以后,不會把之前過程中的op log都傳過去,只需要重新進行一次初始化操作,讓兩端進行同步恢復就可以了。

數據同步的架構演進

剛才講的業務方面的內容可能比較枯燥,接下來就是我們技術架構的演進過程。

首先看一下我們技術架構的特點,跟其他傳統業務不太一樣,屬于寫多讀少。因為讀只需要讀一次到客戶端以后,讀客戶端的副本就可以了,而且一些修改操作直接修改客戶端本地,再由終端同步到云端,剩下的操作大部分都是寫操作。寫同步當然是越實時越好,但問題就是讀的性能肯定會有一些延遲,后面會詳細講解。

我們實現的是最終一致性,因為這不是強一致性的架構,很多客戶端可以關注同一個數據節點的變化。因為我們采用最終一致性,所以會導致多個客戶端可以同時進行寫操作,就必然會產生寫沖突的問題,所以并行寫沖突的問題也要解決。

實時性是我們的特點,這里暫時不詳細說。

最后一個是冪等操作。

這是0.1版本的架構框圖,這個主要面向我們的初期用戶,用來驗證我們產品是否被用戶認可。這個架構由一個接入層組成,用來維護和客戶端的長連接,如果有一個請求過來,會產生數據操作到數據處理,數據處理直接寫Mysql。

Mysql這塊兒直接用了主從同步的模式來保留一定的可用性,然后再進行數據推送。數據推送的時候,先從Redis集群中進行lookup操作,這個操作的目的是尋找要修改的數據節點被哪些終端所關注,然后再進行push操作。

這里的數據采用了物化路徑存儲,也就是說,如果存的是/a/b/c的數據,實際上是存/a一條/a/b一條,/a/b/c一條。

業務得到認可之后,需要對早期用戶有一個性能的保證,所以就有了這個0.2版本的架構框圖,把之前的Mysql改成了mongodb。使用mongodb的原因是可以動態創建數據庫,把用戶的數據在APP級別進行隔離,這樣不會互相影響。同時,mongodb也帶來了讀寫性能的提升。

同時我們采用了副本集多活,利用mongodb自己的副本集主掛了之后自動切從的方案。

機槍換導彈的意思是之前是一次一次對數據庫進行操作,現在我們做了批量的操作和合并的push。之前的操作一個push會影響多個數據節點發生變化,會一條一條的推給關注的終端,現在可以做一個合并的push。

當我們的產品進入bate版測試之后就需要面向廣大的公測用戶了,我們逐漸要面對的就是寫壓力了。因為mongodb的寫操作對于同一個數據表是鎖表的,所以寫是一個串行的性能問題,所以我們這里加了一個寫緩沖隊列,這是大家都會想到的解決方案。

我們這里使用了kafka。一條數據來了之后,由生產者進入kafka,然后由消費者把kafka的數據拿出來進行批量消費,最后內存生成一個操作樹的緩存,再批量寫入mongodb。這塊兒更類似Nagle算法,達到一定的操作量或者達到一定的超時時間后,就同步到Mysql數據庫。

可能大家有過加寫緩沖的經驗,這時候肯定會面臨讀性能下降的問題。因為這時候我們在讀到mongodb的時候是一個已經過時的數據快照,有一些操作還暫存在kafka,寫緩存隊列中,所以必須要解決這個讀不一致的問題。當讀操作來的時候,先從mongodb中讀取到快照,然后再記錄你當前執行到哪,一共有哪些操作還未執行。讀取完之后,在內存進行一個回放操作,拿到的就是比較新的快照版本了。

但是這里還有一個問題,在操作的過程中,還會有新的寫操作過的內容,就算回放完,也是過期的版本。這里有點像redis的主從同步一樣,拿到內存的最后版本后還有新過來的寫操作進入push和wait隊列,先把歷史版本推給客戶端,再把之后的寫操作一次推給客戶端。最后在客戶端進行計算達到的就是最終一致性,用戶拿到的就是最新的數據版本。

在beta版發布一段時間之后,服務器的負載是很平穩的上升,延遲是10、11、12ms,每周是這樣一種遞增。但是突然有一天我們發現延遲暴增到上百ms,甚至到700ms,我們開始各種排查。但是查過之后,kafka、mongodb等等,都一切正常,最后才查到原來是因為push這里需要查一次redis造成的。也就是說,我們在redis中存的是路徑Key,路徑下面是有哪些客戶端節點關注了這個key,所以這里要進行一次模糊匹配查詢,當一個實例的redis數據量到達20w、30w條的時候,如果用模糊查詢性能會非常低,延遲會達到幾百ms。所以我們這里采用了臨時方案,用mongodb來代替redis,用mongodb加它的索引來提升模糊查詢的性能。

這里也為我們敲了個警鐘,我們需要做性能監控,才能真正的面對用戶。后來我們就基于flume做了一套自己的性能監控。Flume可以統計日志,還有對每一個系統延遲的調用,以及異常報警,都寫入flume,再做一個flume的后臺處理。

我們在設計架構的時候,總是把我們的關注點放在最容易發生問題的位置,而往往有時候雖然你解決了這塊兒的問題,但是由于總量上來了,還會影響一些原來不關注的地方出現問題,完全出乎意料。

數據同步的細節問題

剛才是簡單架構框圖的介紹,現在是我們數據同步面臨的一些細節的介紹。

兩個客戶端同時修改本地的副本,需要考慮到數據的靜態一致性,同時還要考慮到寫隔離的問題。對于這個問題其實有兩個解決方案:一是中心化鎖機制;另外一個是進程間協商機制。但是鎖機制會有單點故障問題。所以我們做了一個分布式樹形鎖機制。不過這里有一些需要注意的問題:1、tryLock和release 需要2次的交互;2、需要注意注冊Lock的有效期;3、要等待Lock超時;4、最好使用動態hash;5、連接異常時退化。

還有一些性能問題,因為每個App都有一個樹形鎖,所以是單進程就算你進行了這種操作,在理論上是會有一個吞吐量的上限的。任何操作都要先去嘗試先獲得鎖,這個操作其實是一個浪費的操作。主要性能的點有兩個:一個是單次push sync量比較大,可以導致阻塞。另外一個就是異步push sync。

因為以上這些原因,一個惡心的架構就誕生了。主要因為縮減了write操作的過程,還有要保證云端與客戶端的一致性。整個系統就會太過于復雜,不確定因素太多。

但是我們做技術不能意淫。在真實的應用場景中,有同一客戶端場景和不同客戶端場景。但是兩者所占的比例是不一樣的。不同客戶端的寫沖突有0.3%,同一客戶端寫沖突有4.1%。所以說,其實沖突的概率是非常小的。用上面那種方式就會有種“殺雞焉用宰牛刀”的感覺。

所以,我們提出了一個理念:讓上帝的歸上帝,野狗的歸野狗。具體到實施上就是讓用戶進行可配置化,主要有四種方式:1、默認不啟用;2、減少不必要的開銷;3、降低鎖粒度;4、由appld hash改進為path hash。在這里技術的同學就要注意了,有些問題其實不需要多么厲害的架構,如果能在業務層面進行解決,就盡量將問題在業務層面解決,不要做特別復雜的架構去解決一些虛無縹緲的問題。

要解決這些問題,主要還是依賴寫時的樹形鎖,達到順序push的效果。如果沒有這個操作,就會出現客戶端數據不一致的問題,所以push順序很重要,一定要一致。

主要是需要保證同一客戶端的順序性。以“太空站”這個游戲為例。飛機走著走著回發生回退的現象,造成這個現象的原因,是因為客戶端在進行寫處理的時候是進行并行處理的。這個問題很好解決,可以按照客戶端ID散列到每一個數據處理的進程上,在數據處理進程內部達到一個數據寫一致的效果。進程內的鎖也要實現順序性,所以目標又變成了解決write的性能。

第四個問題就是最終一致性的問題,剛才我們說的都是云端和被同步客戶端之間的問題。

但是這塊兒還會產生的問題模型是客戶端A在本地先做修改,由1修改成2,將2同步到云端以后,云端也修改成2,云端再push到其他的客戶端,對這個數據有關注的,也會修改成2,這樣就解決了最終一致性的問題。

看似很完美,但還是有漏洞。

剛才所做的這一切,只能保證云端和被同步的客戶端的數據是一致的,但是這種情況由于客戶端可以都先對本地進行修改,客戶端A修改成2,客戶端B修改成3,在推送到云端的過程中,A進行的修改會寫入,B進行的修改也會寫入。最后執行的時候如果在云端執行的時候是以某種順序推送過來的,假設云端最后生成的是2那就是說,云端和左側是一致的,就會與另一側的節點產生不一致。

也就是說,由于并行寫,最后會有一個客戶端產生不一致的問題。

這里我們也沒有用到一些復雜的算法,用了一個push給自己的模型來化解這個問題,達到最終的一致性。在并行寫和推送的時候仍然推送給自己,由于推送的過程是串行的,只有推送完前面的一次,才會推送對這個節點的下一次改變操作。這個推送完畢以后,因為是TCP的,所以會按順序推送過去,那就可以認為,在這個推送過程中,所有終端都達到了一致性。

會產生的問題大家也可以看到就是可能會出現,數據由2修改成3,再修改成2。在這里我們需要對一致性問題和性能做一個取舍,當然還是選擇為了達到實時,所以采用這種比較弱的最終一致性方案。

最后一個問題,是一個原子性問題,因為我們是冪等操作,所以不會支持if then,i ++的操作。我們在這里用了一個自旋鎖的CAS機制,在本地拉到數據之后做一個hash,這個hash和要修改的值做一個復合操作一起發到云端,而云端也對這個數據進行一個hash,如果兩個hash是一致的,那才能認為可以操作,才能覆蓋。如果不一致的話,重新從云端再次同步一些數據到本地產生一些副本,進行上一步的操作,直到成功為止。不過我們也有一個重試次數,現在的設置是20次。

今天的演講就到這里了,謝謝大家。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/11710.html

相關文章

  • 用小程序·開發打造功能全面的博客小程序實戰

    摘要:用小程序云開發將博客小程序常用功能一網打盡本文介紹博客小程序的詳情頁的功能按鈕如何實現,具體包括評論點贊收藏和海報功能,這里記錄下整個實現過程和實際編碼中的一些坑。考慮到小程序本身的大小限制,使用的方式是最佳的。 用小程序·云開發將博客小程序常用功能一網打盡 本文介紹mini博客小程序的詳情頁的功能按鈕如何實現,具體包括評論、點贊、收藏和海報功能,這里記錄下整個實現過程和實際編碼中的一...

    cc17 評論0 收藏0
  • 用小程序·開發打造功能全面的博客小程序實戰

    摘要:用小程序云開發將博客小程序常用功能一網打盡本文介紹博客小程序的詳情頁的功能按鈕如何實現,具體包括評論點贊收藏和海報功能,這里記錄下整個實現過程和實際編碼中的一些坑。考慮到小程序本身的大小限制,使用的方式是最佳的。 用小程序·云開發將博客小程序常用功能一網打盡 本文介紹mini博客小程序的詳情頁的功能按鈕如何實現,具體包括評論、點贊、收藏和海報功能,這里記錄下整個實現過程和實際編碼中的一...

    flybywind 評論0 收藏0
  • 10行代碼實現小程序支付功能!實戰

    摘要:前面給大家講過一個借助小程序云開發實現微信支付的,但是那個操作稍微有點繁瑣,并且還會經常出現問題,今天就給大家講一個簡單的,并且借助官方支付實現小程序支付功能。只需要一個簡單的云函數,就可以輕松的實現微信小程序支付功能。 前面給大家講過一個借助小程序云開發實現微信支付的,但是那個操作稍微有點繁瑣,并且還會經常出現問題,今天就給大家講一個簡單的,并且借助官方支付api實現小程序支付功能。...

    SimpleTriangle 評論0 收藏0
  • 用小程序·開發兩天搭建mini論壇實戰

    摘要:筆者最近涉獵了小程序相關的知識,于是利用周末時間開發了一款類似于同事的小程序,深度體驗了小程序云開發模式提供的云函數數據庫存儲三大能力。 筆者最近涉獵了小程序相關的知識,于是利用周末時間開發了一款類似于同事的小程序,深度體驗了小程序云開發模式提供的云函數、數據庫、存儲三大能力。關于云開發,可參考文檔:小程序·云開發。 個人感覺云開發帶來的最大好處是鑒權流程的簡化和對后端的弱化,所以像筆...

    沈建明 評論0 收藏0
  • 巧用小程序·開發實現郵件發送功能實戰

    摘要:七調用云函數發送郵件我們在文件里寫一個按鈕,當點擊這個按鈕時就發送郵件。到這里我們就完整的實現了微信小程序云開發使用云函數發送郵件的功能了。 先看效果圖: showImg(https://segmentfault.com/img/remote/1460000020151412); 通過上面的日志,可以看出我們是158開頭的郵箱給250開頭的郵箱發送郵件,下面是成功接收到的郵件。 sho...

    sixgo 評論0 收藏0

發表評論

0條評論

shmily

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<