蘇寧O2O在異地多活架構與存儲的深度實踐

1. 前言

一般而言,業界的大型互聯網公司往往採用分佈式系統架構,衡量分佈式架構的核心在於高可用(High Availability)。

根據CAP理論,服務分區容錯(Partition Tolerance)是不能捨棄的,因此,對於AP系統可用性(Availability)、CP數據一致性(Consistency)的選擇,決定了分佈式系統的設計思路。

以往簡單的系統會部署在單地域單機房,但大型互聯網公司,從SLA的角度出發,設計中一般都不採用這樣的單點架構,從單機房、同城雙活、異地災備、再到異地多活、單元化,多數互聯網公司都是從類似架構過渡過來的,本文着重從架構和存儲兩方面的角度來講述。

2. 概念

所謂異地多活,是指在多個不同物理地域之間同時提供業務流量和商業服務,各個地域之間不是主備關係,各個地域有自己獨立的基礎設施以及數據中心,業務流量可以不均等的分配在某幾個地域之間。它與異地冷備相比,不僅具有更高的成本優勢,而且更具有可擴展性。

因爲異地多活,實際上就是讓各個地域同時承擔部分業務流量,緩解單一地區的業務壓力。另外,與冷備相比,異地多活爲業力提供了更快速地的業務恢復能力。當某一地域出現不可用時,業務流量可以隨時在不同地域之間進行相互切換,達到了在提供商業可持續性的同時,進行流量動態分配。

3. CAP

提到異地多活,就涉及分佈式系統和數據庫,就不得不提一下著名的CAP理論,可以簡單概括爲以下三句話:

  1. C(Consistency):A read is guaranteed to return the most recent write for a given client.
  2. A(Availability):A non-failing node will return a reasonable within reasonable amount of time(no error or timeout).
  3. P(Partition Tolerance):The system will continue to function when network partitions occur.

一般而言,CA是無法兼得的,P是無法放棄的,所以一般而言,所有分佈式系統的設計,要麼保AP,要麼保CP,用一張圖說明:

4. 業界概念與方案

4.1 單機房

目前的應用一般部署在公有云平臺上,硬件方面,包括網絡、電力、散熱都是冗餘的。服務方面,通過集羣模式來減少機器、機架故障造成的影響,對於SLA要求不高的應用基本能滿足要求。

但單機房部署在整體組網架構中存在單點隱患,一旦出現機房級故障,服務只能暫停並等待恢復,災害性事故導致服務長時間中斷所引發的資損以及社會效益損失,都是企業無法承擔的。所以對於大型互聯網公司,例如BAT等,都會考慮服務的冗餘,比如“同城雙活”或者“同城災備”。

4.2 同城雙活和同城災備

同城雙活和同城災備的差別在於兩個機房是否都跑流量。

單機房遇到機房故障,如斷網、斷電等便停止服務,同城機房可彌補這個弊端。由於同城機房物理上距離足夠近,機房之間通過光纖專線連接,跨機房調度的時延一般可以忽略不計(<3ms),在部署方面和單機房相比並未提高複雜性。

分層方面:

  • 接入層:CDN、4層代理、7層代理、網關,可以選擇隨機的路由方式,如隨機、輪詢、權重、一致性哈希等,也可以選擇有目的性的路由策略,如主機房優先、同機房優先、自定義路由規則等。
  • 服務層:設計爲無狀態的,應用之間用SOA框架連通,如Dubbo、Spring Cloud、Istio等,內部可以橫向擴展,具備auto scaling能力。

  • 存儲層(以一般數據庫作例子,高端存儲設備不作描述):一般互聯網公司使用MySQL,數據拓撲架構爲Master-Slave,採用主從複製(async或semi-sync),在數據中心切換之前,僅在主數據中心進行寫操作,同步到非主數據中心的數據庫,便於主庫故障時候可以手工或自動切換(failover),減少恢復時間。

但是,這種架構問題主要是僞雙活,主故障時數據一致性無法滿足。解決這個問題的方式是使用分佈式數據庫,利用Paxos、Raft分佈式一致性協議保證強一致(這部分後文將會介紹)。

4.3 異地多活和異地災備

同城雙活能解決架構上的單點問題,但依然無法擺脫地域性的災難,如地震、洪水等自然災害,跨地域部署鏡像災備機房和服務便成爲進階考慮。

但跨地域部署的最大挑戰是網絡時延,一些網絡延時的經驗數據如下:

  • 北京-南京 1000公里+ 25ms
  • 南京-廣州 1300公里+ 30ms
  • 同地域 30-50公里 2-3ms
  • 同機房 <1ms

如果服務調用關係複雜,多次的跨地域調度,加上網絡抖動,異地部署的時延往往會比較可觀,對業務正常開展也會有負面影響,所以一般異地備份機房只做災備,採用非對等獨立部署(更小規模、各層獨立部署)不承載業務流量,存儲基於數據庫同步機制進行復制。

這種同城雙活+異地災備的架構,一般稱爲“兩地三中心”架構,即兩個地域,三個IDC。

同城雙活+異地災備對於中等應用基本足夠了,但是對於大型互聯網應用,依然不能接受:

  1. 流量和數據量極大,BAT這種體量,備份機房不跑流量,對於數據一致性要求很高的場景,有一定風險,後文將會講到;
  2. 對於可用性要求極高,4個9的SLA水平,全年停服不能超過1個小時,恢復時間(RTO)取決於預案的執行情況;
  3. 備份全站,資源利用率低,成本高;
  4. 擴容困難,伸縮性受限,計算、存儲、網絡等資源受限於單地域的容量。

異地多活架構下,地域之間不是主備關係,不同物理地域之間同時提供業務服務,不涉及到故障切換failover的工作(流量會有策略調度),而failover的災備策略往往不是自動化的,而且一般比較複雜,需要測試演練,所以維護成本,切換的風險很高。

異地多活下,各個地域機房獨立運行,流量可以按策略調度到各個地域和可用區,與異地災備相比:

  1. 具備更快的業務恢復能力。流量動態分配,一個區域宕機,流量可以自由在各個地域間調度、切換。在某些場景甚至還可以支持就近原則,用戶訪問更快。
  2. 預期和非預期的機房故障可以做容災演練、機房維護,這些對業務都是透明的。
  3. 不用備份全站,成本低。
  4. 伸縮性好,服務和數據可以相對平衡負載在各個區域,不受單地域資源限制。

需要說明的是,並不是所有業務都需要做異地多活,一般對主鏈路業務、SLA要求較高、擴容頻繁的業務優先做,否則方案會比較複雜,工作量也比較大。

4.4 單元化

實現了異地多活,也並不代表到達了終點。

異地多活主要的問題在跨地域延時上,業界目前的解決方案主要集中在網絡層面(搭建BGP網絡、CDN加速等)。在架構層面,阿里在2016年提出的 “單元化”(unit)概念,意思是讓特定user的請求和數據收斂和封閉在同一個IDC,單元高內聚,儘量減少跨區域訪問,即“單元封閉”。一些流量較小的長尾應用,仍然只在中心部署,配套容災方案。

單元化的策略是按照某個業務維度拆分用戶,例如線上商城和支付APP一般是按照會員id(userid)取模劃分單元的,物流一般是按照user所處的地域劃分。每個IDC根據URL設定路由策略調度流量,並封閉服務和存儲,只承載本單元的請求。

4.5 數據庫的高可用

對於傳統數據庫,需要額外配套HA策略來切換Master和Slave。MySQL在本區域或者跨區域的高可用,可以通過主從複製(replication)+多副本(replica)實現,一個實例做Master,其它實例做Standby,主故障即可切換,其他可以做本區域或者跨區域的複製,只做只讀,擴展讀能力。

假設有5000對MySQL主備實例,另外又有一套用來切換MySQL主備實例的HA工具,要做到任意一臺主庫宕機,HA都能夠在極短的時間內切換主備,需要做到的包括:

  1. 部署監控代理

爲了監控各個主庫的狀態,需要在各臺機器上部署Agent以採集實例健康狀態。Agent以一定時間,不斷的向HA彙報實例的健康狀態(Heartbeat)。

  1. Heartbeat與仲裁節點

這些實例的的健康信息如果存放於一個節點上,也存在單點風險。因此需要把這個風險分散到多個節點上,這些節點稱爲仲裁節點。

  1. 數據一致性

接下來就是數據一致性了,下節會介紹。

到這裏,HA也已經是一個分佈式系統了,一般都會馬上想到ZK,因此,對於分佈式集羣的管理,最終還是繞不過Paxos數據一致性協議,基於這種思路,業界涌現了很多分佈式數據庫的解決方案,這塊後面介紹。

4.6 數據的一致性

對於傳統關係型數據庫,無論是Oracle還是MySQL,最通用的做法是通過存儲共享或者日誌同步來保證。

  1. Oracle的存儲共享

比較著名的就是oracle的RAC(Real Application Cluster),基於share everything架構,比如3個節點的RAC系統,在CPU、內存上是做了擴展,但是爲了保證數據強一致性,存儲做了共享。但這種架構最大的弊端就是各個節點爭用熱點塊而引起的“GC”(Global Cache)等待事件。引起“GC”事件的原因,就是同時只能有一個節點在更新同一個塊。Oracle RAC在Fusion Cache層做了內存鎖,用以協調各個節點對於同一個Block的Update操作。Block有資源Master概念,只有得到Master的授權,才能對塊進行更改。因此在架構設計上,Oracle引入了DRM(Dynamic Resource Management)。

另外,爲了解決集羣的腦裂(Brain Split),Oracle引入了基於共享存儲的Voting Disk,來對Brain Split進行仲裁。

這種架構顯而易見的弊端是對硬件依賴非常嚴重,任何存儲介質的異常,都必須進行容災切換,並且無法做到跨機房部署,也就做不到IDC間的容災了。而基於Paxos一致性協議的分佈式數據庫系統,很容易做到這一點,將其中一個副本存放於其它IDC中即可。

  1. 日誌同步

日誌同步,對於性能的損耗比較大。無論是Oracle的Data Guard還是MySQL的Binlog同步,對於Master主庫的TPS有明顯的損耗。每次事務commit,必須要等到從庫ACK,併成功應用後,主庫再返回給用戶事務提交信息。業界有非常多的優化方案,如日誌緩衝區鎖優化、異步化、減少不必要的context switch等,但網絡開銷這塊,即使採用萬兆網、調優網卡軟中斷模式,也改善不了多少。

以MySQL爲例,如果採用Replication(異步複製),由於其異步特性,若數據未完成同步即產生切換,則數據會產生丟失,PRO>0,此時被提升爲新主庫的數據自然就與之前的主庫不一致,如果在同步時停止服務,這樣可用性又受到影響,業務是無法接受的。

爲改善Replication帶來的數據不一致,MySQL 提供了semi-sync(半同步複製),即主庫需要接受從庫的ACK(代表同步到Binlog),才返回客戶端成功。對於幻讀,在5.7之後又可以通過設置AFTER_SYNC或AFTER_COMMIT模式來解決,注意開啓semi-sync會影響寫性能。

但開啓semi-sync,也不一定PRO=0,非高負載select的場景下,MySQL通常開啓InnoDB引擎,採用2PC進行提交,在事務Prepare階段寫完Redo log,事務不是commit狀態,需要走到Server層面,Binlog寫成功,才進行解鎖,清理Undo log的commit工作,再返回客戶端。

MySQL支持用戶自定義在commit時如何將log buffer中的日誌刷到log files中,主要方法是通過設置變量innodb_flush_log_at_trx_commit的值來控制Redo Log的刷盤策略:

0:commit時,寫入log buffer中,然後每秒寫入os buffer並同步fsync刷盤,若進程crash,丟失1秒鐘數據。

1:默認模式,commit時,寫入os buffer並同步fsync刷盤,安全,但需要等待磁盤IO,性能差。

2:commit時,僅寫入os buffer,然後每秒fsync()將os buffer中日誌寫入到log file disk中,比0安全,比2快,若宕機,丟失1秒數據。

同時,可以通過調整參數innodb_flush_method的值來控制Redo Log的打開、刷寫模式,對於這個參數,有4個值:

  • fdatasync:默認,調用fsync()去刷數據文件與redo log的buffer。
  • o_dsync:InnoDB會使用o_sync方式打開和刷寫redo log,使用fsync()刷寫數據文件。當write日誌時,數據都write到磁盤,並且元數據也需要更新,才返回成功。
  • o_direct:InnoDB會使用o_direct打開數據文件,使用fsync()刷寫數據文件跟redo log,write操作是從MySQL InnoDB buffer裏直接向磁盤上寫。
  • all_o_direct:與o_direct差別在於redo log也直接向磁盤上寫。

這4個策略的選擇最終影響的是CPU、處理性能和響應時間。

Sync_Binlog控制Server層面Binlog的刷盤策略。

在事務prepare階段,當MySQL進程Crash或者系統宕機,Binlog是否傳輸到從庫,相應的文件有沒有落盤,都會造成客戶端、主庫、從庫的數據不一致。MySQL的主從,再加上刷盤,是不能保證數據強一致的。如果採用semi-sync+強制刷盤的策略,可以做到不丟數據,但是MySQL實例之間的數據一致性是無法保證的。

比如,redo log或者Binlog任意一方丟了,那麼客戶端會感知失敗,主庫恢復時會rollback,如果Binlog同步到了從庫就生效了,從而出現主從不一致。

爲了滿足可用性要求,減少數據不一致,有一些策略可以優化,例如,主庫宕機恢復後,先禁寫,避免新數據寫入主庫導致不一庫,等把gap diff apply到從庫上,如果沒有衝突,再恢復;否則,採用手工對帳訂正數據。

可用性不強求覆蓋100%的用戶,原則上滿足大部分用戶纔是關鍵。

面對跨地域的高時延和網絡抖動,遠距離同步Binlog有很多侷限性。所以,存儲層面的數據同步在業界會採用DRC中間件解決,比較常用的是Otter和DRC(Data Replication Center),DRC對比Otter,其更關注業務的劃分,可以實現單元內封閉,而Otter只是在純數據庫層打通的技術。

這類中間件的原理爲:從數據庫同步Binlog,異步的將數據進行解析、過濾、標準格式化(DRC Message)、複製遠程傳輸,中間件本身可以做持久化,便於實現一次訂閱,多點分發。可以在事務一致性的前提下提供秒級的DB同步,這種方式注重AP,犧牲了異地一致性。

在單元化異地多活的架構裏,DRC可以承擔單元和中心之間的數據複製功能:可以採用寫中心、讀單元的模式:中間數據廣播到各單元,單元通過中心做數據同步。也可以各單元部分寫,相互同步。這樣請求可以做單元封閉,單元內的數據可以是全量的,支持了區域故障時候的機房切換。

4.7 分佈式數據庫

分佈式數據庫,比較熟悉的比如開源的TiDB、阿里雲的RDS,Google的Spanner等。它們基於Paxos協議或者Paxos簡化變種Raft來實現分佈式系統的數據最終一致性。

Paxos有兩種實現思路,一種是將Paxos與實際的數據節點獨立出來,如zk,這種架構比較簡單,但是因爲增加了Leader和Follower的通信而帶來了更大的時延。另一種是直接將Paxos實現到各數據節點的組件中,好處是時延低、但技術難度高,比如螞蟻的OceanBase、Google的Spanner等。

分佈式數據庫對數據的每次修改都看作一次增量log,通過在存儲上套一層Raft協議。例如,三個節點的集羣,Raft的Leader負責寫,Leader的事務日誌同步到follower,超過多數派(majority quorum)落盤後,再commit。雖然延遲明顯高了,但小幅延時卻可以保證數據一致性,而吞吐可以靠集羣和拆分解決。

可以存在很多的Raft Group,數據按照Range進行分區,還可以做二級分區,這種sharding效果等同於分庫分表,而擴展性、靈活性和容災能力更好。傳統的數據庫強調ACID,而分佈式數據庫可以實現雙A,即加上Availability,只要有半數以上的節點正常就能保證分佈式數據庫正常工作,當Leader節點故障時發起Leader election自行恢復,無需人工switch over或者failover。

而阿里雲的RDS,其原理也是在MySQL內核上套用一個Raft狀態機控制事務,保證了數據的一致性,由於分佈式數據庫依賴Paxos或者Raft,所以延遲更是問題,一般部署在同地域,依賴DRC(DTS)做異地複製。

分佈式數據庫單Group至少3個節點,更加可靠的方案可以採用5個節點,以三地五中心架構舉例,Zone1和Zone2同城雙機房,Zone3和Zone4同城雙機房,一個距離稍遠的可以設計爲僅做日誌副本,節省空間,同時減少高延時帶來的吞吐量下降,可做到PRO=0,RTO幾十秒,強一致,可抵禦個別硬件故障、機房級災難和區域級災難。

5. 蘇寧O2O的異地多活

以上內容全部基於線上2C業務,但O2O的異地多活有所不同。

首先,蘇寧O2O以線下業態爲主,包括蘇寧易購、蘇寧小店、蘇鮮生、蘇寧極物等。但接入方式多種多樣,比如設備,既包含Pos機、收銀一體機等終端設備,也包含自助收銀機、機器人、電子稱等智能設備,同時包含各種APP,如店+。APP走LocalDNS+CDN的方式接入,而終端設備在接入層面以專線+VPN爲主,無法通過CDN進行流量調度,每家門店都建立多條專線的成本也無法承受。即使採用中心交換匯聚,也會面對各種單點問題。

其次,由於DB層面缺少雙向同步能力,目前在DB層面依賴MySQL自帶的異步數據同步(Replication)和半同步(semi-sync),根據之前的描述,數據一致性無法得到保障,增加網絡延時與抖動的風險。

最後,O2O有兩層數據維度,一層是門店維度,另一層是用戶維度,這也區別於一般的2C業務,複雜度增加。

根據上述的情況,需要在架構和數據層面進行整體性考慮,見O2O的未來架構:

5.1 接入層

1、網絡方面:

蘇寧小店\迪亞店\大潤發\店+ 等,原先通過VPN接入數據中心,後在門店中部署無線AP對接Wi-Fi或直連網線。

電器門店的收銀機,原先通過SDH Line或ADSL(IPsec)設備,走專線和VPN接入,先到達分公司核心交換機,再通過大區核心交換機進行轉發。後也通過無線AP接入或有線連接的方式。

2、流量層面:

業務請求域名指向爲CDN,終端請求流量經DNS解析後,就近接入CDN,由CDN根據一定規則(shopid或userid取模)調度不同數據中心。

在數據中心,流量先經由WAF進行安全清洗,對於Https請求則卸載SSL,並調度到後端集羣Gateway VIP,由網關負責將Http協議轉爲RSF協議(RPC)調用後端服務

3、安全層面:

前端與後端的請求經由Https進行加密,終端設備接入需要進行安全認證。

5.2 服務間調用

  1. 服務的劃分

蘇寧O2O也採用了類似單元化的概念,將所有數據與服務在單元內封閉,稱爲Unit。Unit由一組包含服務+數據的業務集羣組成,稱爲Cell。請求的數據按照Cookie中的MA字段進行切分,關於Cell和MA,後面有介紹。

根據服務性質的不同,將服務區分爲共享、獨佔和競爭服務。

1)共享服務:

每個數據中心部署一套Cell,所有Cell擁有相同的數據,相互共享。該類數據在所有Cell內都是一致的,對於每個Cell都是全量,才能支持本Cell完成業務。例如商品、價格、檔口等數據。

2)獨佔服務:

每個數據中心部署一到多套Cell,對應的服務和數據僅在某個Cell存在,不與其它Cell交叉或共享。其它Cell不需要本Cell的數據即可完成內部業務,如會員、訂單、購物車。

3)競爭服務:

只在主數據中心部署一套Cell,該類型數據存在各個Cell相互競爭,爲保證數據的一致性,需要在一個數據中心統一控制讀寫,例如庫存、領劵、時效控量、唯一編碼、用戶註冊的用戶名唯一性等。

  1. 服務間調用方式

1)RPC調用

蘇寧內部提供RSF框架(類似於Dubbo),服務之間通過ZK集羣註冊和發現,接口間通過RPC協議相互訪問。RSF在不同DC部署不同註冊中心實例,多個註冊中心組成一個集羣,內部進行數據同步,兩個機房的生產者實例分別向對應的註冊中心註冊RSF服務,並且可以指定該服務的調用是路由到相同機房或主機房。

對於獨佔服務,由於數據被封閉DC內部,因此調用獨佔服務的RSF接口一般採用路由同機房策略。有一些涉及不同維度結合的場景,可能會涉及多DC數據匯聚的場景,由將索引維度及匯聚下沉到中臺。

對於共享服務,寫操作的RSF服務路由主機房,讀操作RSF服務路由同機房。

對於競爭服務,只在主機房部署,因此全部路由主機房。

2)MQ

蘇寧內部提供WindQ(類似於ActiveMQ),僅限於異步業務,業務需要支持消息的冪等操作。有二種模式,分別是Queue模式(一對一)和Topic模式(一對多),生產環境主要採用Topic模式。

目前在WindQ的消息隊列管理系統上,Topic模式的路由策略由消費者定義,支持三種路由類型:同機房、主機房和全路由。

服務類型 說明 路由策略
獨佔服務 獨佔型服務的數據封閉在LDC內,主要採用同機房路由,消費者只能接收到來自同機房生產者發送的數據 同機房路由
共享服務 對於寫操作,採用主機房路由,主機房的消費者可以接收來自所有機房生產者發送的數據;對於讀操作,採用同機房路由,消費者接收到來自同機房生產者發送的數據 寫:路由主機房讀:路由同機房
競爭服務 競爭服務只在主機房部署,因此全部路由主機房 路由主機房

Topic模式還有種全路由方式,類似於一種廣播模式,全路由模式下,所有消費者可以接收到所有機房生產者發送的數據,類似於全網刷新廣播。

3)Kafka

業務需要在各個機房生產數據,然後每個機房的數據需要彙總到某一個機房來進行消費統計,目前主要採用主機房匯聚。

4)定時任務

服務類型 DUTS運行模式 說明 備註
獨佔服務 單機運行或分片運行 LDC選擇所有機房執行 或 定義2個任務,分別選擇主機房和指定機房 正常情況採用單機運行,若任務數較多,可設置分片數,將不同任務分片分發到不同機器上去運行
競爭服務 單機運行或分片運行 LDC選擇主機房執行
共享服務 單機運行或分片運行 LDC選擇主機房執行 底層通過數據庫進行同步

5.3 數據層面

由於缺少DB層面的雙向同步能力,爲降低數據不一致的風險,需要考慮合理的數據切分規則,減少數據之間的同步,收斂跨機房請求。

1、數據劃分

如果將每個Cell作爲一套包含服務+數據的業務集羣。那麼每個Cell的數據庫單獨作爲一個物理數據庫存在,不允許Cell之間的交叉訪問,即同一個庫內不允許有不同Cell的數據。

由於目前數據庫備份方式採用交叉互備,並且需要保證同一Cell的數據要能夠收斂在同一個LDC中,因此,需要對於獨佔型數據定義分佈規則。

Cell之間可以交叉互備,最小的互備單元爲兩個Cell集合(cellId,cellId+4)。獨佔型數據的分佈方式參考Ma的切片規則:

MA類別 計算方式
tradeMA memberUID % 256
shopMA acsII(shopUID)% 256

分庫分表策略:每個應用的分表數爲256N,分庫個數爲8M+1。M和N代表自然數。

類型 分表策略(獨佔) 分庫策略(獨佔) 多活單元劃分(CellId, CellId+4)
tradeMA tableId= memberUID % (256*N) dbId = tradeMA %(8M),其中,tradeMA=255單獨分配到庫8M (dbId,dbId+4)作爲一個最小子單元,子單元兩兩遞歸組成更大子單元,cell255單獨做一個單元
shopMA tableId= acsII(shopUID) % (256*N) dbId = shopMA %(8M),其中,shopMA=255單獨分配到庫8M (dbId,dbId+4)作爲一個最小子單元,子單元兩兩遞歸組成更大子單元,cell255單獨做一個單元

2、數據一致性

對於不同的服務,有不同的一致性策略。

對於共享服務(多DC數據一致):每個DC都部署一套集羣,該集羣包含全量數據,共享服務數據的變更請求只能通過主DC操作,類似於master-slave模式,若請求流量是非主DC發起,則通過跨中心RSF或MQ方式進行處理。主DC數據變更後,底層通過MySQL Replication實現數據同步。

對於獨佔服務(根據不同數據分片獨立存儲):在多個DC根據數據分片策略部署多套集羣,每個集羣封閉自身的操作和數據,但在本DC和跨DC通過其它Cell實現數據備份,當某LDC數據變更後,通過MySQL Replication實現數據同步。

對於競爭服務(控制資源,如權益、餘額等),只在主數據中心進行CRUD,其它DC部署鏡像服務和數據,但只同步,不調度流量。

正常情況下,數據同步的時延是毫秒級,但DB數據備份在網絡中的傳輸受到距離、網絡抖動等因素影響,可能存在一致性風險,考慮有以下策略:

  • 減少數據同步:只同步重要數據,減少不重要數據及同步後沒用的數據的同步。比如待支付清單,丟失後重新查詢生成支付列表即可。
  • 保證最終一致性:在業務邏輯中,儘量減少對數據同步實時性的依賴,只要數據能最終一致即可。比如當某件商品新增了折扣,在數據同步完成之前,查詢了商品價格,對於這種情況,只要保證最終扣款和打印發票時,折扣已經被計算入內即可。

3、數據備份

不同集羣結對,數據交叉互備。

4、緩存

對於獨佔服務,Redis需要跨機房備份,備份思路參考MySQL備份策略,機房A-master-node -> 機房A-slave-node -> 機房B-slave-node,同步策略爲準實時同步,當主機房宕機時請求引流到備份機房時,組件根據tradeMA或是shopMA路由到對應的Redis服務。當主機房恢復時,需要將備份機房中主機房對應的備份Redis中的數據全量複製(RDB)到主機房對應的Redis,然後再恢復主機房進行引流。

對於共享服務,採用主機房讀寫,副機房只讀的主從單向備份。

緩存加載首先通過懶加載方式加載數據到緩存中,由於更新或刪除無法通過懶加載加載到緩存的,通過canal讀取MySQL Binlog捕獲對應的變更信號,並更新到緩存中。

緩存預熱通過數據庫複製方式同步到各個數據中心,然後通過canal讀取MySQL Binlog來觸發緩存加載(推薦),或通過業務變更數據庫時,同步變更緩存(視情況採用該方案)。

6. 參考文檔

1、《High-Avaliability at Massive Scale:Building Google`s Data Infrastructure for Ads》

作者介紹:

榮多君,蘇寧科技集團O2O平臺研發中心副總監,在蘇寧從事負責O2O新零售業務及平臺建設,目前負責中心繫統多活及互聯網化改造工作。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章