多終端數據同步機制設計

来源:http://www.cnblogs.com/ben121011/archive/2016/09/12/5865995.html
-Advertisement-
Play Games

多終端數據同步機制設計(一) Intro 因為項目需要,需要設計一個多終端數據同步的機制, 需要滿足以下條件: 1. 多個終端數據操作及同步 2. 每次同步的時候只拉取需要同步的數據,且數據不能存在丟失 3. 儘可能少的調用伺服器端介面 同步流程 整體同步流程 我想仿照Git數據同步的方式來進行數據 ...


多終端數據同步機制設計(一)

Intro

因為項目需要,需要設計一個多終端數據同步的機制, 需要滿足以下條件: 1. 多個終端數據操作及同步 2. 每次同步的時候只拉取需要同步的數據,且數據不能存在丟失 3. 儘可能少的調用伺服器端介面

同步流程

整體同步流程

我想仿照Git數據同步的方式來進行數據同步,於是放著Git同步的流程來進行設計,首先每次提交會有一個版本號,另外每次提交之前應儘可能先從伺服器端拉取數據, 保證客戶端的數據是最新的情況下再進行提交本地的修改。按照Git的方式來進行數據同步時,可能會存在數據衝突,如果存在數據衝突需要客戶端解決衝突。
也就是總體來說,操作有兩個大的操作,一個是從伺服器端拉取數據,一個是向伺服器端推送數據更新。
在資料庫層面有一個數據版本表來存儲每一次提交,每一次更新會在更新結束之後將在版本表中加上一條記錄,更新一個版本,並將版本號返回給客戶端, 每次從伺服器端拉取更新的時候不僅會將更新的數據返回給客戶端,也會將最新的版本號返回到客戶端,用以客戶端下一次同步數據。

最後伺服器端提供了三個介面

  1. GetCurrentVersion() 查詢用戶數據的最新版本號,
  2. PullData() 從伺服器端拉取更新數據,
  3. PushData() 向伺服器端推送本地數據更新

思慮再三之後最終產出了下麵的流程圖:

 

從伺服器端獲取用戶數據的最新版本號

客戶端調用 GetCurrentVersion() 介面,需要傳遞一個標識用戶賬號的參數,這樣才能查詢到某一個用戶的數據信息。 根據用戶賬號信息查詢數據的最新版本號,返回到客戶端,客戶端根據伺服器端的版本號和本地進行比較,如果一致則說明是最新版本之後判斷本地是否有修改有修改則直接提交即可,如果不一致一定不是最新版本則進行伺服器端拉取數據更新數據和版本號後再提交本地修改(如果有修改)。

從伺服器端拉取數據流程

從伺服器端拉取更新有些麻煩,如果在一臺設備上有幾個版本沒有更新的話,需要考慮將幾個版本的數據合併,具體問題以及流程在後文中會提及。

從伺服器端拉取數據基本流程如下:

 

客戶端拉取數據後更新本地數據流程

客戶端調用 PullData 介面 從伺服器拉取本地需要修改的數據同時每一條數據都對應一個操作狀態來更新本地數據,從伺服器端返回數據的同時返回數據對應的操作狀態,客戶端根據返回的操作狀態對數據進行相應的處理,返回數據時也需要將最新數據的版本號也返回用以客戶端更新本地數據版本。

 

客戶端向伺服器推送更新

客戶端調用 PushData 介面向伺服器端推送更新,將需要提交的修改提交到伺服器端,伺服器端返回客戶端每一個需要進行修改的數據的操作狀態,是否修改成功。

伺服器端更新數據

客戶端向伺服器端推送更新之後,伺服器端需要進行處理。 首先需要判斷客戶端的版本是否是最新版本,如果不是最新則提示客戶端先更新本地數據到最新版本再更新數據,如果是最新的再向下處理。 之後需要將客戶端的請求數據(一個json字元串)反序列化轉換為請求實體列表,如果轉換失敗則說明客戶端的請求數據是有問題的則不進行處理,如果轉換成功再向下處理。 然後遍歷請求實體列表,根據請求數據的操作類型進行不同數據操作,每條數據操作完之後設置對應的操作狀態。 最後所有請求數據更新完成之後,新增一個版本,並將版本設置到響應。

 

被我踩到的那些坑

Pull 數據版本合併

從伺服器端拉取數據的時候需要考慮到多個版本的提交數據合併問題,我們的數據比較簡單是直接更新原來的數據,因此不會涉及到文本分塊再合併這一類太複雜的操作,但是也需要將幾個版本的修改進行合併,例如新增數據,兩個版本各新增兩條數據則應返回四條數據才對,一個版本新增另一個版本刪除掉的數據就不應該返回給客戶端。 這就需要考慮如何高效並且準確的返回客戶端需要更新的數據,這裡需要提及一下我的版本表的涉及,版本表裡除了版本號之外有更新人,更新時間和每次調用 PushData 介面時的請求參數和返回給客戶端的操作狀態集合的響應的轉換為json字元串存儲在資料庫中,每次更新完數據之後在版本表中插入一條新的版本數據。

解決方案一:

第一種方式,首先我考慮從版本表裡取出每次修改成功的數據,再將多個版本的修改進行合併到一個List,再去重,如果遇到兩條相同的數據需要進行去重操作,需要根據每條數據的操作類型來判斷該如何具體的去重,大致分四種情況:

  1. 先新增後修改 --> Add
  2. 先新增最後刪除 --> null 不需要返回給客戶端
  3. 先修改之後還是修改 --> Update
  4. 先修改最後刪除 --> Delete

這裡不僅操作類型需要修改,數據內容也是需要進行合併的,需要最新的數據返回。

解決方案二:

第二種方式,按照版本的更新時間和數據的創建時間和更新時間的關係來進行篩選數據和判斷數據的操作類型,如果數據刪除的話只是修改數據的狀態並不真正的刪除數據。

首先將更新時間大於本地版本對應的版本更新時間的數據查詢出來,這些數據是在本地版本更新之後的所有數據, 之後篩選數據,按操作類型可分四種情況:

  1. 創建時間 >= 版本更新時間 && IsDeleted = 0 --> Add
  2. 創建時間 >= 版本更新時間 && IsDeleted = 1 --> null 先創建後刪除,不需要返回到客戶端
  3. 創建時間 < 版本更新時間 && IsDeleted = 0 --> Update
  4. 創建時間 < 版本更新時間 && IsDeleted = 1 --> Delete

篩選並判斷操作類型之後將數據返回給客戶端

綜合比較,確定版本合併方案

經過分析,第一種方案數據操作起來非常麻煩,相對的第二種解決方案數據操作會很少,可以在資料庫層面進行判斷篩選,至於數據準確度方面兩者差不多, 考慮併發問題的話可以在 調用 Push 介面時根據用戶賬號進行加鎖,綜合一下,最終採用第二種解決方案。

Push介面

調用Push介面的時候原本沒有判斷本地的版本號,如果出現客戶端沒有按照設定的順序來調用介面可能就會出現不可想象的數據災難,而且作為介面本身是沒辦法控制客戶端的調用順序的。 所以,修改後的 Push 介面需要客戶端傳遞一個客戶端版本號的參數,如果不是最新版本的數據拒絕提交,並提示客戶端先更新數據到最新版本後再提交數據。

時間不統一

這個問題算是自己給自己挖的坑,在更新數據的時候時間取的都是網站伺服器端時間,但是在新增版本的時候新增的參數里的更新時間用的卻是資料庫伺服器的時間,由於資料庫伺服器和網站伺服器不在一臺伺服器上, 資料庫伺服器的時間比網站伺服器上的時間慢了幾秒,這導致我在從伺服器端拉取數據時出現有的數據沒有拉取出來的情況,後來debug從資料庫中查詢數據確實更新了而且版本也正確插入了,最後一一記錄每一條數據的更新時間和每個版本的更新時間, 這才發現時間有點不太對,再檢查下自己的sql語句,發現新增版本的sql的更新時間用的是GETDATE(),而更新數據的sql都是參數,用的是網站伺服器的時間。。發現問題的我頓時想抽死自己...(

In the end

最後,這個設計一定還存在著不足,希望大神看到能給出自己的看法和意見,有不正確的地方還希望能夠告知。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 將特定用戶代理的別名添加到用戶代理別名的內部集合中。 來自 <https://msdn.microsoft.com/zh-cn/library/6379d90d(v=vs.110).aspx> 用戶代理別名的集合指示 ASP.NET 伺服器控制項應為其呈現內容的目標用戶代理。其信息可以在Page.Cl ...
  • Google的ProtoBuf序列化器性能的牛逼已經有目共睹了,可以把它應用到Socket通訊,隊列,Wcf中,身為dotnet程式員一邊期待著不久後Grpc對dotnet core的支持更期待著Wcf有一天能在Linux平臺上閃瞎所有人。現在簡單表述下Wcf中應用ProtoBuf替代預設的序列化器 ...
  • 前言 面向對象的思想已經非常成熟,而使用C 的程式員對面向對象也是非常熟悉,所以我就不對面向對象進行介紹了,在這篇文章中將只會介紹面向對象在F 中的使用。 F 是支持面向對象的函數式編程語言,所以你用C 能做的,用F 也可以做,而且通常代碼還會更為 簡潔 。我們先看下麵這個用C 定義的類,然後用F ...
  • 1、目標 1、目標 代碼編寫規範、整齊、整潔、可讀。 無錯誤 無警告 2、排版 2、排版 安裝PowerCommands擴展 “工具”-“擴展管理庫”,搜索安裝。 設置選中Format document on save和Remove and Sort Usings on save 這樣代碼保存時會自 ...
  • 走進非同步編程的世界 - 剖析非同步方法(下) 序 感謝大家的支持,這是昨天發佈《走進非同步編程的世界 - 剖析非同步方法(上)》的補充篇。 目錄 異常處理 在調用方法中同步等待任務 在非同步方法中非同步等待任務 Task.Delay() 暫停執行 一、異常處理 await 表達式也可以使用 try...cat ...
  • 不知道可能稱的上是ORM,其實就是一個DBHelper。看到網上不少人寫自己的ORM,但我覺得都不太好。 我這個ORM,學習成本非常低,常用的方法僅有幾個,在使用的過程中,你不需要有太多要註意的地方,也不會有“我怎樣實現連表查詢”的疑問。反射犧牲一些性能,但是降低了實現和使用的複雜度。 支持Orac ...
  • 一、前言 MD5驗證主要用於更新文件功能方面,伺服器告知客戶端要下載哪些更新文件並提供給客戶端其MD5值,客戶端從伺服器將更新文件下載到本地並計算下載文件的MD5值,將本地接收的MD5值與伺服器提供的MD5值進行比對,如果相同則說明下載的文件與伺服器提供的文件是一致的,如果不相同則說明下載後文件可能 ...
  • 剛開始學習Halcon,需要使用Halcon與C++聯合開發軟體,查了網上的資料都是Halcon10的,我用的是Halcon11和VS2010的開發環境,實踐了一下發現有一些問題,於是把自己的配置的過程寫出來共用一下。 首先新建一個Halcon工程,這裡用個讀入圖片的簡單例子。 新建一個Halcon... ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...