在線聊天系統(tǒng)中的多窗口數(shù)據(jù)同步技術(shù)解密
我在業(yè)余時(shí)間開發(fā)了一款自己的獨(dú)立產(chǎn)品:升訊威在線客服與營(yíng)銷系統(tǒng)。其中有些功能,我一直認(rèn)為是客服系統(tǒng)應(yīng)該有的基本功能,應(yīng)該沒必要單獨(dú)拿出來說。直到總會(huì)有客戶專門和我說起和他們?cè)瓉硎褂玫南到y(tǒng)的對(duì)比,我才知道真的是很多所謂的客服系統(tǒng),真是一言難盡。

升訊威在線客服與營(yíng)銷系統(tǒng)走的是免費(fèi)與分享路線,我會(huì)通過文章分享客服系統(tǒng)一些重要且基本的功能是如何實(shí)現(xiàn)的,以及它們的技術(shù)方案,部分代碼。希望對(duì)您有用。
在本文中,我將詳細(xì)說明訪客端聊天窗口的多窗口數(shù)據(jù)同步技術(shù)。該技術(shù)能確保訪客端在網(wǎng)頁多開,刷新,關(guān)閉再打開等復(fù)雜情況下,收發(fā)的消息完全同步,并且可靠送達(dá):

技術(shù)路線
對(duì)于多窗口數(shù)據(jù)同步,一般有三種技術(shù)路線:
一、同一瀏覽器內(nèi)多個(gè)標(biāo)簽頁之間的數(shù)據(jù)同步
1. BroadcastChannel API
隨著現(xiàn)代 Web 應(yīng)用朝著多標(biāo)簽頁、多窗口協(xié)同的方向演進(jìn),如何實(shí)現(xiàn)同一瀏覽器上下文內(nèi)的高效數(shù)據(jù)同步機(jī)制成為關(guān)鍵技術(shù)挑戰(zhàn)之一。傳統(tǒng)方案多依賴 localStorage 的 storage 事件或 SharedWorker,但存在性能瓶頸、同步延遲大、調(diào)試?yán)щy等問題。
為此,W3C 推出了 BroadcastChannel API,這是一種瀏覽器原生支持的同源上下文間廣播通信機(jī)制,允許不同標(biāo)簽頁、iframe、甚至獨(dú)立的瀏覽器窗口之間進(jìn)行高效、即時(shí)的數(shù)據(jù)傳輸。
- 應(yīng)用場(chǎng)景:
** 多標(biāo)簽協(xié)同編輯:多個(gè)標(biāo)簽頁打開同一文檔時(shí),實(shí)時(shí)同步編輯狀態(tài)。
** 跨頁面登錄狀態(tài)共享:在一個(gè)頁面登錄后,其他頁面同步刷新用戶信息。
** 在線聊天窗口彈出同步:主窗口與彈窗之間共享消息隊(duì)列。
** Web 通知廣播:在一個(gè)窗口觸發(fā)操作,其他窗口同步顯示提示信息。
** 數(shù)據(jù)緩存在標(biāo)簽間共享:避免多標(biāo)簽重復(fù)拉取后端資源,減少 API 請(qǐng)求頻率。
- 用途:在同一源(域名)下的多個(gè)標(biāo)簽頁/iframe之間進(jìn)行通信
- 優(yōu)點(diǎn):簡(jiǎn)單、現(xiàn)代瀏覽器支持較好
- 用法示例:
const channel = new BroadcastChannel('my_channel');
channel.postMessage({ key: 'value' });
channel.onmessage = (event) => {
console.log('Received:', event.data);
};
技術(shù)挑戰(zhàn)與優(yōu)化方案
異常頁面斷聯(lián)
當(dāng)某些頁面處于掛起狀態(tài)(如后臺(tái)標(biāo)簽頁被系統(tǒng)凍結(jié)),消息廣播可能延遲。建議通過 heartbeat ping 機(jī)制輪詢活躍連接,并在失聯(lián)時(shí)移除通道監(jiān)聽器。
安全性
BroadcastChannel 在同源策略下無加密驗(yàn)證,任何同源頁面都可加入通信。為避免數(shù)據(jù)被惡意監(jiān)聽,建議:
對(duì)數(shù)據(jù)使用結(jié)構(gòu)簽名(如 HMAC)。
添加信道協(xié)議版本字段,避免協(xié)議升級(jí)時(shí)兼容性問題。
在主通道封裝認(rèn)證層,非認(rèn)證者拒絕處理消息。
2. LocalStorage + StorageEvent
HTML5 引入了 LocalStorage,它是一種在瀏覽器本地存儲(chǔ)數(shù)據(jù)的方式,允許網(wǎng)頁存儲(chǔ)少量的數(shù)據(jù),并且數(shù)據(jù)會(huì)持久化存儲(chǔ),即使頁面關(guān)閉后依然可以訪問。
然而,當(dāng)多個(gè)頁面需要共享同一份數(shù)據(jù)時(shí),傳統(tǒng)的 JavaScript 變量和函數(shù)無法有效地實(shí)現(xiàn)跨標(biāo)簽頁的數(shù)據(jù)同步。在此背景下,HTML5 又引入了 StorageEvent,該事件可以偵聽 LocalStorage 中的數(shù)據(jù)變化并實(shí)時(shí)通知其他窗口或標(biāo)簽頁。
LocalStorage
LocalStorage 是一種 Web 存儲(chǔ)機(jī)制,它允許以鍵值對(duì)的形式將數(shù)據(jù)存儲(chǔ)在客戶端。每個(gè)域名(Origin)都擁有自己獨(dú)立的 LocalStorage 空間,最大存儲(chǔ)容量一般為 5MB 左右,且存儲(chǔ)的數(shù)據(jù)在瀏覽器關(guān)閉后仍然存在,直到被顯式刪除。
StorageEvent
StorageEvent 是一個(gè)用于監(jiān)聽 LocalStorage 或 SessionStorage 數(shù)據(jù)變化的事件。該事件觸發(fā)時(shí),其他瀏覽器窗口或標(biāo)簽頁能夠接收到來自該源的更新,并可以立即響應(yīng)這些變化。這個(gè)特性使得它成為跨頁面、跨標(biāo)簽頁通信的重要手段。
StorageEvent 觸發(fā)時(shí),事件對(duì)象會(huì)包含變化的詳細(xì)信息,如被修改的存儲(chǔ)鍵、修改前的值、修改后的值、以及修改發(fā)生的窗口/標(biāo)簽頁等信息。
- 用途:通過
localStorage寫入觸發(fā)其他標(biāo)簽頁的storage事件 - 限制:當(dāng)前標(biāo)簽頁寫入不會(huì)觸發(fā)自己,無法監(jiān)聽自己寫的值
- 用法示例:
localStorage.setItem('sync_key', JSON.stringify({ data: 123 }));
window.addEventListener('storage', (e) => {
if (e.key === 'sync_key') {
console.log('Storage updated:', JSON.parse(e.newValue));
}
});
3. SharedWorker
SharedWorker 允許在多個(gè)瀏覽器上下文(如多個(gè)標(biāo)簽頁、窗口或 iframe)之間共享一個(gè)單獨(dú)的后臺(tái)線程,這為前端開發(fā)提供了一種跨標(biāo)簽頁、跨窗口共享計(jì)算資源的高效解決方案。
SharedWorker 是一種瀏覽器 API,允許多個(gè)標(biāo)簽頁、窗口或 iframe 共享同一個(gè)后臺(tái)線程(Worker)。這意味著,多個(gè)頁面或標(biāo)簽頁可以通過該共享 Worker 執(zhí)行一些復(fù)雜的計(jì)算任務(wù)、存儲(chǔ)數(shù)據(jù)或執(zhí)行其他異步操作,從而節(jié)省計(jì)算資源和提高響應(yīng)速度。
與傳統(tǒng)的 Web Worker 相比,SharedWorker 通過 port 對(duì)象讓不同頁面之間能夠通信,多個(gè)瀏覽器上下文可以通過這個(gè)共享的 Worker 進(jìn)行數(shù)據(jù)交換。這使得 Web 開發(fā)者能夠更好地管理并發(fā)任務(wù)和共享資源。
- 用途:多個(gè)標(biāo)簽頁共享一個(gè)Worker線程,可用于持久連接、共享狀態(tài)
- 優(yōu)勢(shì):適合統(tǒng)一WebSocket連接、集中式狀態(tài)管理
- 限制:不能在不同域名或跨瀏覽器窗口間工作
二、同一用戶不同設(shè)備之間的數(shù)據(jù)同步
1. WebSocket
WebSocket 是一種在單個(gè) TCP 連接上進(jìn)行全雙工通信的協(xié)議,旨在解決傳統(tǒng) HTTP 協(xié)議在實(shí)時(shí)數(shù)據(jù)交互中的局限性。它由 IETF 于 2011 年發(fā)布,并成為 Web 標(biāo)準(zhǔn)的一部分。與 HTTP 請(qǐng)求-響應(yīng)模型不同,WebSocket 允許客戶端與服務(wù)器之間保持長(zhǎng)時(shí)間的連接,并且可以在任何一方需要時(shí)進(jìn)行實(shí)時(shí)數(shù)據(jù)交換。它的工作流程可以分為兩個(gè)階段:建立連接和數(shù)據(jù)傳輸。首先,客戶端通過 HTTP 發(fā)起 WebSocket 握手請(qǐng)求,服務(wù)器響應(yīng)確認(rèn)后,HTTP 連接升級(jí)為 WebSocket 連接。此時(shí),客戶端和服務(wù)器之間的連接將保持開放,可以進(jìn)行雙向數(shù)據(jù)傳輸,直到其中一方主動(dòng)關(guān)閉連接。WebSocket 的最大優(yōu)勢(shì)在于它提供了低延遲、高效率的雙向通信。相比于傳統(tǒng)的輪詢和長(zhǎng)輪詢方法,WebSocket 使得數(shù)據(jù)交換更加實(shí)時(shí),避免了頻繁的連接建立與斷開,從而減少了網(wǎng)絡(luò)延遲和帶寬消耗。適用于需要高頻率實(shí)時(shí)通信的場(chǎng)景,如在線聊天、實(shí)時(shí)游戲、股票行情推送、社交媒體更新等。在這些應(yīng)用中,客戶端與服務(wù)器之間需要頻繁交換小數(shù)據(jù)量,并且需要盡量減少延遲。
- 用途:實(shí)現(xiàn)客戶端與服務(wù)器的長(zhǎng)連接,支持服務(wù)器主動(dòng)推送消息
- 適合:聊天室、多人協(xié)作、實(shí)時(shí)數(shù)據(jù)更新等
- 方案示意:
- 客戶端A發(fā)送變更到服務(wù)端
- 服務(wù)端廣播給其他客戶端B/C/D
2. WebRTC + Signaling Server
WebRTC(Web Real-Time Communication)是一項(xiàng)允許瀏覽器和移動(dòng)應(yīng)用進(jìn)行點(diǎn)對(duì)點(diǎn)通信的技術(shù),它支持音視頻通話、文件共享以及實(shí)時(shí)數(shù)據(jù)交換,且無需用戶安裝插件。WebRTC 的核心優(yōu)勢(shì)在于其低延遲、高效的數(shù)據(jù)傳輸能力,尤其適用于實(shí)時(shí)通訊、視頻會(huì)議、在線游戲等應(yīng)用場(chǎng)景。
然而,WebRTC 本身僅處理媒體流的傳輸和點(diǎn)對(duì)點(diǎn)通信,但它不提供建立和管理連接的機(jī)制。在 WebRTC 中,客戶端之間的連接通常需要借助一個(gè)信令服務(wù)器(Signaling Server)來交換元數(shù)據(jù)(如網(wǎng)絡(luò)地址、連接請(qǐng)求、ICE 候選等),以便協(xié)商和建立 WebRTC 的點(diǎn)對(duì)點(diǎn)連接。
WebRTC 與信令服務(wù)器的結(jié)合非常適合需要實(shí)時(shí)音視頻通信的應(yīng)用,如視頻會(huì)議、在線教育、遠(yuǎn)程醫(yī)療、實(shí)時(shí)客服等。信令服務(wù)器通常使用 WebSocket、HTTP 或其他協(xié)議來實(shí)時(shí)傳輸信令數(shù)據(jù)。在這些應(yīng)用中,信令服務(wù)器確保客戶端可以快速、有效地建立連接,并在需要時(shí)進(jìn)行協(xié)商和更新。
典型的 WebRTC 應(yīng)用流程如下:
- 用戶A和用戶B通過瀏覽器訪問應(yīng)用,雙方通過信令服務(wù)器交換 SDP 和 ICE 候選。
- 信令服務(wù)器傳遞信息后,WebRTC 在用戶A和用戶B之間建立點(diǎn)對(duì)點(diǎn)連接,直接進(jìn)行媒體流的傳輸。
- 連接成功后,雙方可以進(jìn)行實(shí)時(shí)的音視頻交流,數(shù)據(jù)流的傳輸不再通過信令服務(wù)器,信令服務(wù)器僅用于初期的協(xié)商和后續(xù)的斷開通知。
- 用途:瀏覽器對(duì)瀏覽器之間的點(diǎn)對(duì)點(diǎn)通信
- 適合:低延遲協(xié)作、文件傳輸
- 注意:需要中間的 signaling server 來建立連接
三、多個(gè)用戶、多設(shè)備的高頻協(xié)作場(chǎng)景
1. 服務(wù)端事件推送(Server-Sent Events, SSE)
Server-Sent Events (SSE) 是一種用于在客戶端和服務(wù)器之間進(jìn)行單向?qū)崟r(shí)通信的技術(shù)。通過 SSE,服務(wù)器可以主動(dòng)向客戶端發(fā)送數(shù)據(jù)更新,而客戶端則無需頻繁發(fā)送請(qǐng)求。這種技術(shù)基于 HTTP 協(xié)議,允許服務(wù)器將更新數(shù)據(jù)推送到客戶端,使得瀏覽器能夠即時(shí)接收到服務(wù)器端的最新信息。
工作原理
SSE 的工作原理相對(duì)簡(jiǎn)單,客戶端通過建立一個(gè)持久的 HTTP 連接,向服務(wù)器發(fā)送一個(gè)請(qǐng)求。服務(wù)器接收到請(qǐng)求后,保持這個(gè)連接打開,并定期發(fā)送新的數(shù)據(jù)流到客戶端。與 WebSocket 不同,SSE 是單向的通信,數(shù)據(jù)僅從服務(wù)器流向客戶端,因此適合用于需要實(shí)時(shí)推送數(shù)據(jù)但不需要頻繁從客戶端向服務(wù)器發(fā)送數(shù)據(jù)的應(yīng)用場(chǎng)景。
- 用途:從服務(wù)端單向推送消息給客戶端
- 優(yōu)勢(shì):比輪詢節(jié)省資源,兼容性好于 WebSocket(但只支持單向)
- 適合:低頻實(shí)時(shí)通知、數(shù)據(jù)變動(dòng)提醒等
應(yīng)用場(chǎng)景
SSE 適用于各種需要實(shí)時(shí)推送信息的應(yīng)用,特別是以下幾種場(chǎng)景:
- 實(shí)時(shí)通知:如社交媒體平臺(tái)、消息應(yīng)用、新聞網(wǎng)站等,可以通過 SSE 向用戶實(shí)時(shí)推送新的通知或消息。
- 股票行情與金融數(shù)據(jù):SSE 非常適合實(shí)時(shí)推送股票行情、加密貨幣價(jià)格等更新,這些信息需要快速和持續(xù)地發(fā)送給客戶端。
- 在線游戲:在多人在線游戲中,SSE 可以用來推送游戲狀態(tài)的變化,如玩家位置、得分更新等。
- 監(jiān)控系統(tǒng):用于實(shí)時(shí)監(jiān)控系統(tǒng)狀態(tài)、日志、傳感器數(shù)據(jù)等,可以將實(shí)時(shí)信息推送到客戶端進(jìn)行展示。
2. 基于 CRDT 或 OT 的協(xié)同算法
CRDT 是一種通過設(shè)計(jì)特殊的數(shù)據(jù)結(jié)構(gòu)來解決數(shù)據(jù)沖突的技術(shù),常用于去中心化的系統(tǒng)中。CRDT 確保即使多個(gè)用戶并發(fā)修改同一數(shù)據(jù),最終所有節(jié)點(diǎn)的狀態(tài)也會(huì)達(dá)成一致,且無需額外的沖突解決機(jī)制。CRDT 基于數(shù)學(xué)原理,通過保證操作的交換性和結(jié)合性,使得不同節(jié)點(diǎn)之間的操作順序無關(guān),從而自動(dòng)解決沖突。
CRDT 常見的類型有:
- 計(jì)數(shù)器:比如增量計(jì)數(shù)器或可撤銷的計(jì)數(shù)器,支持在不同節(jié)點(diǎn)獨(dú)立遞增或遞減。
- 集合:如元素集合,可以無沖突地并行添加或刪除元素。
- 有序集合:如有序隊(duì)列,確保不同節(jié)點(diǎn)間的順序一致。
OT 是一種經(jīng)典的協(xié)同算法,廣泛應(yīng)用于在線協(xié)作編輯工具中,如 Google Docs 等。OT 通過記錄操作并將其轉(zhuǎn)化為獨(dú)立的變更單元,在并發(fā)編輯時(shí)進(jìn)行順序轉(zhuǎn)換,確保每個(gè)用戶的編輯操作能夠在其他用戶的操作基礎(chǔ)上無沖突地合并。OT 的核心思想是將用戶的操作轉(zhuǎn)換成可以相互轉(zhuǎn)換的“操作單元”,并確保每個(gè)操作都能被正確地應(yīng)用在其他操作之前或之后。例如,兩個(gè)用戶同時(shí)插入文字時(shí),OT 會(huì)根據(jù)操作發(fā)生的順序自動(dòng)調(diào)整插入位置,從而避免沖突。優(yōu)勢(shì)在于它能夠提供高效的實(shí)時(shí)協(xié)作,適用于需要精細(xì)控制并發(fā)編輯的場(chǎng)景,但它需要中心化的服務(wù)器來協(xié)調(diào)和管理操作。
- 用途:實(shí)現(xiàn)高性能多人實(shí)時(shí)協(xié)作
- 方案:
- CRDT(Conflict-free Replicated Data Types)
- OT(Operational Transformation)
OT 協(xié)同算法
升訊威在線客服系統(tǒng)使用了最先進(jìn)的 OT Operational Transformation)協(xié)同算法,來達(dá)到頁面多開、刷新、飛行模式,聊天不中斷,消息不丟失。
OT 算法基本原理詳解
OT(Operational Transformation)算法是一種強(qiáng)一致性的同步模型,最早應(yīng)用于軍事協(xié)同文檔系統(tǒng)中,其核心思想是通過操作的變換與融合機(jī)制,來實(shí)現(xiàn)多客戶端并發(fā)編輯下的數(shù)據(jù)一致性。該算法適用于文本編輯器、代碼協(xié)作工具、在線聊天系統(tǒng)等需要毫秒級(jí)響應(yīng)和沖突消解能力的場(chǎng)景。
一、核心概念
OT 的核心基于如下三個(gè)概念:
- 操作(Operation):對(duì)數(shù)據(jù)執(zhí)行的原子變更,例如插入、刪除或替換。在文本場(chǎng)景中表現(xiàn)為 Insert 或 Delete。
- 版本(Revision):服務(wù)器記錄的操作版本號(hào)。每個(gè)客戶端操作基于某個(gè)版本生成,當(dāng)多個(gè)客戶端同時(shí)提交變更時(shí),就可能引發(fā)版本分叉。
- 變換函數(shù)(Transformation Function):用于將兩個(gè)沖突操作變換為可以連續(xù)執(zhí)行的不沖突版本,確保最終數(shù)據(jù)一致。
二、原理說明:并發(fā)操作的協(xié)調(diào)
假設(shè)兩個(gè)客戶端用戶 Alice 和 Bob,分別在同一文本 "Hello" 上并發(fā)進(jìn)行了如下操作:
- Alice:在第 5 位插入
"!",操作記為Insert(5, "!")。 - Bob:在第 0 位刪除
"H",操作記為Delete(0, 1)。
由于這兩個(gè)操作是基于同一個(gè)版本發(fā)起的,服務(wù)器需要將其進(jìn)行轉(zhuǎn)換,使得它們可以連續(xù)作用于同一個(gè)數(shù)據(jù)副本。這就是變換函數(shù)的作用:
- 將 Alice 的操作根據(jù) Bob 的操作進(jìn)行變換(Transform)。
- 更新位置偏移或刪除區(qū)間,調(diào)整 Alice 的操作為:
Insert(4, "!")。 - 然后按順序應(yīng)用:先刪,再插。
這樣,無論服務(wù)器先收到誰的操作,最終都會(huì)得到一致的數(shù)據(jù)狀態(tài):"ello!"。
三、核心算法流程(偽邏輯)
Client:
1. 用戶在本地執(zhí)行操作 O。
2. 將操作 O 和當(dāng)前客戶端版本號(hào) R 一并發(fā)送到服務(wù)器。
Server:
1. 獲取歷史操作 H = allOps[R:]
2. 對(duì) O 與每個(gè)歷史操作 h ∈ H 執(zhí)行變換 O = transform(O, h)
3. 應(yīng)用 O 到數(shù)據(jù)模型
4. 將變換后的 O 及新版本號(hào)廣播給所有客戶端
四、OT 算法的變換
在變換過程中,位置的偏移是關(guān)鍵。例如:
Insert(3, "X")在Delete(0, 2)之后,插入點(diǎn)變?yōu)?1。Delete(4, 1)與Insert(4, "Y")同步發(fā)生,需調(diào)整順序。
五、在聊天系統(tǒng)中的應(yīng)用優(yōu)勢(shì)
OT 算法不僅適用于文檔編輯,在在線聊天系統(tǒng)中也有廣泛應(yīng)用,尤其是在以下模塊中:
- 消息內(nèi)容實(shí)時(shí)協(xié)作:多個(gè)客服同時(shí)編輯一個(gè)回復(fù)草稿。
- 會(huì)話上下文增強(qiáng):AI 插入提示建議內(nèi)容,與人工輸入實(shí)時(shí)融合。
- 聊天記錄修改日志:在已發(fā)送消息上做更改的權(quán)限控制與同步。
- 知識(shí)庫協(xié)作更新:OT 可用于 FAQ 和答案模板的多人共建。
借助 OT 算法,聊天系統(tǒng)可實(shí)現(xiàn)如下目標(biāo):
- 零沖突編輯:避免因多個(gè)用戶同時(shí)修改造成消息錯(cuò)亂。
- 延遲容忍能力:OT 支持異步網(wǎng)絡(luò)環(huán)境中的最終一致性。
- 無鎖協(xié)同體驗(yàn):用戶之間無需等待鎖釋放即可并發(fā)編輯。
六、擴(kuò)展機(jī)制與融合策略
現(xiàn)代 OT 實(shí)現(xiàn)中通常會(huì)結(jié)合以下機(jī)制:
- 多通道融合:在文本 OT 的基礎(chǔ)上,添加結(jié)構(gòu)型操作(如移動(dòng)節(jié)點(diǎn)、合并消息塊)。
- 語義層補(bǔ)充:例如在聊天中加入角色權(quán)限限制,如只有管理員可以 delete 操作。
- AI 協(xié)同增強(qiáng):將 AI 生成的操作作為特殊操作流插入 OT 隊(duì)列。
OT 算法通過“以操作為中心”的機(jī)制,在保持編輯響應(yīng)性的同時(shí)實(shí)現(xiàn)了高一致性,特別適合需要人機(jī)協(xié)同、低延遲互動(dòng)的現(xiàn)代通信系統(tǒng)。
Python 實(shí)現(xiàn) OT 協(xié)同算法:應(yīng)用于在線聊天系統(tǒng)的完整示例
下面我們深入構(gòu)造一個(gè)完整的 Python 工程級(jí)別示例,展示如何實(shí)現(xiàn)一個(gè)適用于在線聊天系統(tǒng)的 OT(Operational Transformation)核心機(jī)制。
一、工程結(jié)構(gòu)概覽
ot_chat/
├── main.py
├── ot/
│ ├── __init__.py
│ ├── operation.py # 操作結(jié)構(gòu)定義
│ ├── transform.py # 操作變換邏輯
│ ├── history.py # 歷史版本跟蹤
│ └── session.py # 用戶協(xié)同會(huì)話管理
└── utils/
└── logger.py # 日志記錄模塊
二、核心代碼模塊
1. operation.py
# 定義基礎(chǔ)操作類型:Insert 與 Delete
class Insert:
def __init__(self, position, content, user_id):
self.type = 'insert'
self.position = position
self.content = content
self.user_id = user_id
class Delete:
def __init__(self, position, length, user_id):
self.type = 'delete'
self.position = position
self.length = length
self.user_id = user_id
2. transform.py
# 用于處理 Insert 和 Delete 操作的變換邏輯
def transform(op1, op2):
if op1.type == 'insert' and op2.type == 'insert':
if op1.position <= op2.position:
return op1
else:
op1.position += len(op2.content)
return op1
if op1.type == 'delete' and op2.type == 'insert':
if op1.position >= op2.position:
op1.position += len(op2.content)
return op1
if op1.type == 'insert' and op2.type == 'delete':
if op1.position <= op2.position:
return op1
elif op1.position > op2.position + op2.length:
op1.position -= op2.length
else:
op1.position = op2.position
return op1
if op1.type == 'delete' and op2.type == 'delete':
if op1.position >= op2.position + op2.length:
op1.position -= op2.length
elif op1.position + op1.length <= op2.position:
pass
else:
# 刪除區(qū)域有交集
overlap_start = max(op1.position, op2.position)
overlap_end = min(op1.position + op1.length, op2.position + op2.length)
op1.length -= (overlap_end - overlap_start)
if op1.length < 0:
op1.length = 0
return op1
3. history.py
class OperationHistory:
def __init__(self):
self.history = []
self.revision = 0
def add(self, op):
self.history.append(op)
self.revision += 1
def get_since(self, revision):
return self.history[revision:]
4. session.py
from ot.history import OperationHistory
from ot.transform import transform
class ChatSession:
def __init__(self, session_id):
self.session_id = session_id
self.document = ""
self.history = OperationHistory()
def apply_operation(self, op, client_revision):
# Step 1: transform op based on history
ops_to_transform = self.history.get_since(client_revision)
for old_op in ops_to_transform:
op = transform(op, old_op)
# Step 2: apply op to document
if op.type == 'insert':
self.document = self.document[:op.position] + op.content + self.document[op.position:]
elif op.type == 'delete':
self.document = self.document[:op.position] + self.document[op.position + op.length:]
# Step 3: store in history
self.history.add(op)
return self.document
5. main.py
from ot.session import ChatSession
from ot.operation import Insert, Delete
if __name__ == "__main__":
session = ChatSession("room1")
print("初始內(nèi)容:", session.document)
op1 = Insert(0, "Hello", user_id="Alice")
result1 = session.apply_operation(op1, client_revision=0)
print("操作1后:", result1)
op2 = Insert(5, " World", user_id="Bob")
result2 = session.apply_operation(op2, client_revision=1)
print("操作2后:", result2)
op3 = Delete(0, 6, user_id="Alice")
result3 = session.apply_operation(op3, client_revision=2)
print("操作3后:", result3)
運(yùn)行結(jié)果(模擬多個(gè)客戶端并發(fā)修改):
初始內(nèi)容:
操作1后: Hello
操作2后: Hello World
操作3后: World
三、適配在線聊天系統(tǒng)的方式
這套 OT 框架可以輕松適配在線聊天系統(tǒng)中的以下模塊:
- 聊天室介紹編輯:多人同時(shí)編輯聊天室信息
- 消息草稿協(xié)同編輯:協(xié)作生成自動(dòng)回復(fù)內(nèi)容
- AI 插入建議修改:修改或注入 AI 建議
- 多客服并發(fā)溝通記錄修訂
通過對(duì)每條消息視為一個(gè)“小文檔”,可以將消息體嵌入 OT 流程中,實(shí)現(xiàn)毫秒級(jí)一致性同步。
四、部署與擴(kuò)展建議
- 可將
ChatSession封裝為微服務(wù),掛載于 Redis 分布式會(huì)話管理中 - 每個(gè)客戶端保留本地
client_revision,與服務(wù)器同步后更新 - 可通過 WebSocket 保持連接,推送變更
結(jié)語
在線客服系統(tǒng)的開發(fā)并非易事,從前端到后端,從數(shù)據(jù)庫到 AI,從性能優(yōu)化到安全保障,每一步都需要深思熟慮。如果你在實(shí)踐中遇到新的問題,或者有更好的解決方案,歡迎在評(píng)論區(qū)分享你的見解,讓我們一起探索更優(yōu)雅的技術(shù)實(shí)現(xiàn)方案!
簡(jiǎn)介下這個(gè) .net 開發(fā)的小系統(tǒng)
升訊威在線客服與營(yíng)銷系統(tǒng)是一款客服軟件,但更重要的是一款營(yíng)銷利器。
- 可以追蹤正在訪問網(wǎng)站或使用 APP 的所有訪客,收集他們的瀏覽情況,使客服能夠主動(dòng)出擊,施展話術(shù),促進(jìn)成單。
- 可嵌入網(wǎng)站、手機(jī) APP、公眾號(hào)、或者通過 URL 地址直接聯(lián)系客服。
- 支持訪客信息互通,可傳輸訪客標(biāo)識(shí)、名稱和其它任意信息到客服系統(tǒng),與您的業(yè)務(wù)系統(tǒng)對(duì)接。
- 可全天候 7 × 24 小時(shí)掛機(jī)運(yùn)行,網(wǎng)絡(luò)中斷,拔掉網(wǎng)線,手機(jī)飛行模式,不掉線不丟消息,歡迎實(shí)測(cè)。


希望能夠打造: 開放、開源、共享。努力打造 .net 社區(qū)的一款優(yōu)秀開源產(chǎn)品。

浙公網(wǎng)安備 33010602011771號(hào)