把可用性拆成四個問題
加第二台閘道之前,先說清楚要備援的是哪一段。網路能連上,不代表只有一個主站會操作設備;備機取得資料,也不代表歷史庫不會重複;畫面有數值,更不代表切換期間沒有缺口。把主站所有權、資料送達、事件去重與品質標記分開設計,才能在故障時知道哪個能力真的接手。
| 問題 | 需要的證據 | 不能拿什麼代替 |
|---|---|---|
| 網路可用 | 路徑及服務健康檢查 | 只看Ping |
| 主站所有權 | 產品支援的仲裁或隔離機制 | 只看對方心跳消失 |
| 資料去重 | 穩定事件識別與提交記錄 | 只比較數值一樣 |
| 資料完整性 | 來源序號、缺口與時間 | 只看備機目前上線 |
本篇採虛構來源S,其事件具有開機世代B7與遞增序號,兩台閘道A、B可取得同一批來源事件。事件識別為S、B7、sequence三欄,gatewayId只記搬運者。如果來源沒有事件序號而由兩台各自輪詢,兩筆相同數值可能是不同採樣,不能照搬本篇的同一事件去重規則。
同時備援讀取與命令寫入時,寫入權特別需要明確安排。兩台TCP客戶端可以連上同一設備,不表示兩個控制命令可任意交錯;兩個RTU主站共用同一條線也不能因叫作主備就自動避免碰撞。正式設計先查閘道、協調系統與設備實際支援的所有權能力。
主機在事件50後失聯的離線案例
假設來源S在B7世代產生事件48至53,主機A已把48、49、50提交到上游資料庫。A在50之後失聯,備機B保有從48開始的重送資料,取得經確認的主站權後依序補送48至53。消費端不能因送達者從A變B就把48至50當成新事件。
| 到達順序 | 搬運者 | 事件鍵 | 消費端結果 |
|---|---|---|---|
| 原先 | A | S/B7/48至50 | 已提交三筆 |
| 恢復1 | B | S/B7/48 | 重複,保留原事件 |
| 恢復2 | B | S/B7/49 | 重複,保留原事件 |
| 恢復3 | B | S/B7/50 | 重複,保留原事件 |
| 恢復4至6 | B | S/B7/51至53 | 新增三筆 |
完成後,正式事件表共有48至53六筆,搬運嘗試記錄則可以有九筆,因為重送本身也是診斷證據。把事件表與送達記錄分開,既不讓趨勢重複計數,也能知道備援曾補送哪些資料。若業務動作是累加產量,必須在同一持久化交易內完成去重判斷與累加,避免先累加後才發現重複。
另一個分支是A把50寫入資料庫,但確認回覆在網路中遺失。A或B稍後重送50,仍應命中同一事件鍵,不能再加一次。通訊確認、訊息代理確認與業務資料庫提交是不同邊界;收到其中一個ACK,不一定代表整條鏈每個動作都已完成。
失去心跳不等於舊主機停止
如果A、B彼此網路斷開,但A仍能連到PLC,B只憑收不到A心跳就取得寫入權,兩台可能同時運作。這就是需要仲裁及隔離舊主機的原因。心跳提供故障懷疑,不能單獨證明舊主機已失去設備存取能力;更快的心跳只能更快懷疑,不能補足所有權證據。
| 情境 | 危險或限制 | 預期設計行為 |
|---|---|---|
| A程式停止 | 主機可能確實不再送出 | 由支援的接手機制確認 |
| A與B斷網 | 兩台都可能看不到對方 | 不得各自宣稱唯一主機 |
| A仍連設備 | 備機接手可能造成雙主 | 先確認舊權限已撤回或隔離 |
| 協調服務失聯 | 無法證明租約仍有效 | 依設計停止取得新控制權 |
| A恢復 | 舊角色不再可信 | 重新加入並同步狀態 |
可採的機制取決於產品,例如原廠冗餘協調、外部仲裁或能真正阻止舊主機的fencing。若設計使用世代權杖,受控服務必須能拒絕舊權杖才有意義;只在兩台閘道日誌寫一個世代號,不會讓不支援的PLC自動拒絕舊命令。本文不發明PLC指令或仲裁API。
切換流程先確認故障條件,再取得新所有權,確認舊主機已被有效隔離,最後啟用需要所有權的輪詢或寫入。對只讀、多客戶端且設備允許的場景,可以有不同策略,但仍要估算額外負載與資料來源。不要把某種監控備援規則直接套到會啟動機械的命令通道。
缺口與晚到資料如何顯示
備機開始補送時,畫面應分開顯示目前資料與歷史補送。假設51的來源時間較早,卻在53之後才到,事件表可接受51補齊缺口,但即時值不能因此倒退成51。用來源世代與序號判定新舊,保留來源時間與接收時間;來源時鐘跳動時,單靠時間排序不足以判斷順序。
若只收到48、49、50、52、53,缺51就先標示缺口待確認。等待期間多久、來源是否可重取及何時宣告永久遺失,均由資料契約決定;不能把序號50的值複製成51再宣稱完整。斷線時保留最後值可以幫助診斷,但品質與最後有效時間必須一起提供。
| 離線驗收 | 輸入事件 | 完成後應看到 |
|---|---|---|
| 正常補送 | B重送48至53 | 事件六筆,重複三筆有記錄 |
| ACK遺失 | 已提交50再收到50 | 業務計數不再增加 |
| 缺口 | 收到50、52、53 | 51缺口明確列出 |
| 晚到 | 53後才到51 | 補歷史,當前值不倒退 |
| 來源重啟 | S/B8/1 | 新世代事件,不能當B7重複 |
若來源序號會回繞,契約必須提供回繞辨識或足夠的世代欄位。若兩台閘道自行產生相同序號48,那只是兩個本機序號巧合,不足以表示同一來源事件。事件鍵選錯會造成兩種相反錯誤:該去重的被重算,或真正的新採樣被刪掉。
測試恢復時也要觀察補送速度。上游處理率若只夠新資料,就無法清掉舊佇列;應量出新增率、補送率與最舊待送年齡,依優先規則安排。備援切換成功與歷史資料補齊可以在不同時間完成,狀態畫面應各自顯示。
FAQ與產品能力限制
FAQ1:兩台有相同IP就是完整高可用嗎?不是。浮動IP只解決部分網路定位,仍需服務狀態、資料同步、唯一控制權、去重及缺口處理,各項都要有獨立驗收。
FAQ2:用gatewayId加sequence當唯一鍵可以嗎?如果A與B是在搬運同一來源事件,加入不同gatewayId反而使重送無法去重。若本來就是獨立採樣,則須保留不同來源身分,不能強行合併。先定義事件從哪裡產生。
FAQ3:MQTT QoS2能取代業務去重嗎?不能從協定交付語意推論兩個發送者、資料庫寫入及累加動作都只執行一次。跨閘道補送仍需穩定事件鍵與消費端提交規則。
FAQ4:主機回來就立刻切回嗎?先查原廠支援的同步與回切流程。舊主機可能有過期設定、未完成命令與待送資料,先確認角色和世代,避免恢復的主機重新搶控制權。
Ignition官方冗餘文件將歷史資料的Full與Partial模式分開,並說明主備網路故障可能造成重複資料;這是特定平台行為的例子,不是任意硬體閘道都有相同模式。本篇S/B7事件鍵與fencing要求是離線架構設計。
參考:Inductive Automation Ignition 8.3 Redundancy,主備同步與歷史資料處理模式。
參考:OASIS MQTT Version 5.0,QoS與會話交付範圍。