異地多活的數據一致性簡單設計

来源:https://www.cnblogs.com/longbozhan/archive/2022/03/16/16011848.html
-Advertisement-
Play Games

概述 異地多活,往往意味著誇機房讀寫延遲的增加,也就增加了讀寫失敗的可能性,最終導致數據的延遲更長,同時,這種場景下也會影響線上系統的性能和時延。本文從數據低延遲、開發複雜度上考慮,總結了兩種處理方式,分別是雙寫和雙讀,從而保證數據的最終一致性。對於異地多活的業務場景,往往也不需要保證強一致性,允許 ...


概述

异地多活,往往意味着夸机房读写延迟的增加,也就增加了读写失败的可能性,最终导致数据的延迟更长,同时,这种场景下也会影响在线系统的性能和时延。本文从数据低延迟、开发复杂度上考虑,总结了两种处理方式,分别是双写和双读,从而保证数据的最终一致性。对于异地多活的业务场景,往往也不需要保证强一致性,允许短时间的不一致性。例如对于外卖软件,在南方点了外卖,然后到北方出差,常规上也不可能短时间内(分钟级别)从南方飞到北方。 再举个极端的例子,我们所看到星空中的行星的光,也很多是很多年前从很远的宇宙发射过来的,你不可能在同一时间看到光。 再者,实现真正的异地多活(强一致,多节点写入)是个极其复杂的工程,需要底层数据库、业务上的支持,对于一致性要求没那么高的业务场景,我们可以选择稍微简单的方案实现。

双写

写入本机房后,还需要写入异地机房,同步方式可以有:
  1. 数据库本身支持了同步:这种情况往往需要增加第三方组件,例如阿里的otter组件支持了mysql的同步。业务代码只需要写一次,底层数据同步交给数据库,会出现短时间的两个机房数据不一致的情况,业务上往往能够接受。但极端情况也会出现异地对同一份数据进行写,导致写写冲突,这时候需要业务介入做抉择(常见的方式如订单系统后期的对账补偿)。如果对于数据库的操作是数据库级别的原子性操作,例如redis的incr命令,就可以避免写写冲突。
  2. 数据库本身不支持同步:这种情况需要业务代码双写,跨区写的失败率会变高,采取重试,但会加剧数据的延迟(如果延迟不高,也能接收)。同时,如果是在线系统,往往并发量比较大,所以还是得在业务层面加MQ,如加入第三方的MQ(如kafka),实现上就得实现producer和consumer逻辑,而且还需要额外对kafka进行维护,这也带来了系统的复杂性。简单做法是采用内存队列,直接写入内存队列,通过定时器定期消费内存队列数据。如果数据支持批量接口,采用批量写数据库,读的时候,只读本机房数据。这种方式,也会有问题:因为是内存队列,如果服务重启,还没来得及消费的数据会丢失;或者是多次写失败重试后依然失败,也会导致数据丢失(其实这种情况需要发出告警,人工介入了)。如果业务允许有一定的数据丢失的情况,但对时效性要求较高的,采用这种方式比较合理。

双读

跟双写的读本机房相反,改成只写本机房,读双机房。这种方式,首先对于高并发的读,非常不友好,跨区读的时延太高,同步读往往会导致超时或者影响在线时延。所以一般采用异步的方式,由一个异步线程把数据从另一个机房捞出来再写入本地机房数据库,读的时候只读本地机房数据库库。这种方式加大了延迟,好处是提高了并发度,尽量的减少对读的影响,而且如果本地支持幂等性,还能保证数据的最终一致。数据从异地同步到本地的机制可以两种:
  1. 全量同步:实现简单,但只适合于数据量少,但如果数据太多,同步也会很慢,加大了延迟,有可能打满网卡导致影响整体服务环境。
  2. 增量同步:实现复杂,需要设置个游标,类似kafka的offset,记录本次同步到的点,如何标准游标是准确的呢?需要保证不多也不少,例如如果游标粒度设置的太大,同一个游标可能对应多个数据,这样可能导致捞过来的数据比原有的多。所以这种情况对游标的选择就比较重要了。

高并发下的优化方案

批量:无论是对于双读还是双写,都采用数据库的批量接口,减少网络io。

异步+双队列缓存

    • 异步:对于双写方案,采用异步写;对于双读方案,采用异步读更新(这种情况除非是增量更新,否则如果全量更新,也会导致性能和延迟的增加;但全量更新就要求数据不能太多,而且如果数据库是redis或者其他kv,需要提前知道对应的key)。
    • 双队列缓存:双buffer是为了提高并发度,对于双写,可以只需要对内存中的写进行互斥,但对于数据的更新不会互斥,因为两者个用不同队列;对于双读,数据结构可以参考我之前发的doublybufferdata数据结构。对于队列,其实是传统MQ的替代,只是如果引入MQ,则需要带来额外的维护成本,所以可以简单的实现,用set或者map都可以。

总结

双读和双写的本质区别其实是数据在哪一边同步的问题,类似kafka的producer和consumer,不可能放在同一个机房,要么producer端是夸机房,要么是consumer端是夸机房。无论是哪种方案,都会面临延迟和不一致问题,以及还有性能问题,要兼顾延迟性、一致性、性能等,实现起来极其复杂,需要根据业务需要选择一种折中的方案。   作者:longbozhan
出处: https://www.cnblogs.com/longbozhan/p/16011848.html
如果您觉得本文对您有帮助,请点击一下右下方的推荐按钮, 如果您对本文有任何疑问并想和作者探讨,请在本文下方评论,我看到后将第一时间回复!
版权声明:本文为博主原创或转载文章,欢迎转载,但转载文章之后必须在文章页面明显位置注明出处,否则保留追究法律责任的权利。
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 裝飾器模式又叫包裝模式,數據結構型模式;是指在不改變現有對象結構的情況下,動態的給改對象增加一些職責(即增加其額外功能)的模式。 在星巴克咖啡店,有美式咖啡(LongBlack)、無因咖啡(Decaf)、義大利農咖啡(Espresso)等不同的咖啡種類,也可以添加牛奶(Milk)、豆漿(Soy)、巧 ...
  • 原型模式是什麼 原型模式是一種創建型設計模式, 使你能夠複製已有對象, 而又無需使代碼依賴它們所屬的類。 為什麼要用原型模式 可以幫助我們優雅地創建對象的拷貝。在這種設計模式裡面,將克隆某個對象的職責交給了要被克隆的這個對象。被克隆的對象需要提供一個clone()方法。通過這個方法可以返回該對象的拷 ...
  • 生成器模式是什麼 生成器模式也叫做建造者模式,是一種創建型的設計模式, 使你能夠分步驟創建複雜對象。 為什麼要用生成器模式 假設有這樣一個複雜對象, 在對其進行構造時需要對諸多成員變數和嵌套對象進行複雜的初始化工作。這些初始化代碼通常深藏於一個包含眾多參數且讓人基本看不懂的構造函數中。而且在很多時候 ...
  • 博客推行版本更新,成果積累制度,已經寫過的博客還會再次更新,不斷地琢磨,高質量高數量都是要追求的,工匠精神是學習必不可少的精神。因此,大家有何建議歡迎在評論區踴躍發言,你們的支持是我最大的動力,你們敢投,我就敢肝 ...
  • 如果你想模仿springMVC,自己編寫一套開發框架,本文將給你答案! ...
  • 微服務在最近幾年大行其道,很多公司的研發人員都在考慮微服務架構,同時,隨著 Docker 容器技術和自動化運維等相關技術發展,微服務變得更容易管理,這給了微服務架構良好的發展機會。 在做微服務的路上,拆分服務是個很熱的話題。我們應該按照什麼原則將現有的業務進行拆分?是否拆分得越細就越好?接下來一起談... ...
  • 作者:霜序 校稿:袋鼠雲數棧前端團隊運營小組 該文章包含如下內容 受控與非受控組件 非受控組件 受控組件 受控和非受控組件邊界 反模式 解決方案 前言 在 HTML 中,表單元素(<input>/<textarea>/<select>),通常自己會維護 state,並根據用戶的輸入進行更新 <for ...
  • 單例模式是什麼 單例模式是一種創建型設計模式:單例模式保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。 為什麼要用單例模式 為什麼要用單例模式?在系統中某些對象,我們只需要一個全局的,如果每次實例化會浪費資源。所以單例模式可以節約記憶體,加快對象訪問速度,因此單例模式在某些場合適合使用。比如多個 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...