楊 坤 李 夏 王 勇 都書剛
( 煤炭科學(xué)技術(shù)研究院有限公司,北京100013)
為實(shí)現(xiàn)人員定位管理系統(tǒng)的可靠性, 煤炭行業(yè)監(jiān)管部門制定的相關(guān)行業(yè)標(biāo)準(zhǔn)要求: 煤礦井下作業(yè)人員管理系統(tǒng)應(yīng)具有雙機(jī)切換功能, 并且從工作主機(jī)故障到備用主機(jī)投入正常工作時(shí)間應(yīng)不大于5min。 因此,井下作業(yè)人員管理系統(tǒng)必須具有穩(wěn)定、可靠的雙機(jī)熱備解決方案?;诿旱V生產(chǎn)場(chǎng)景的實(shí)際,目前的煤礦井下人員定位系統(tǒng)主要是采用純軟件的方式實(shí)現(xiàn)。 純軟件的雙機(jī)熱備系統(tǒng)具有節(jié)約成本與部署方便的優(yōu)點(diǎn), 但現(xiàn)有的純軟件的雙機(jī)熱備系統(tǒng)也存在著一些缺陷:(1) 監(jiān)控服務(wù)狀態(tài)的流程復(fù)雜,造成可靠性差;(2)數(shù)據(jù)同步采用通信程序分發(fā)機(jī)制,易造成數(shù)據(jù)混亂;(3)界面復(fù)雜,操作困難。 針對(duì)現(xiàn)有純軟件方式實(shí)現(xiàn)的雙機(jī)熱備存在的問題, 筆者設(shè)計(jì)了一套基于有限狀態(tài)機(jī)的雙機(jī)熱備系統(tǒng),能夠同時(shí)監(jiān)測(cè)PostgreSQL、Redis 與通訊服務(wù)的工作狀態(tài),形成一個(gè)穩(wěn)定的解決方案,提高了雙機(jī)熱備的可靠性。
有限狀態(tài)機(jī)是指系統(tǒng)中的有限個(gè)狀態(tài)以及狀態(tài)之間的遷移移活動(dòng),并通過狀態(tài)、條件、動(dòng)作與次態(tài)四個(gè)要素構(gòu)建對(duì)應(yīng)的數(shù)學(xué)模型。 狀態(tài):系統(tǒng)具有一組狀態(tài),并且系統(tǒng)可以在這些狀態(tài)之間切換;但是,系統(tǒng)在某一時(shí)刻只能處于一個(gè)狀態(tài)。 條件:觸發(fā)系統(tǒng)進(jìn)行狀態(tài)切換的事件;當(dāng)系統(tǒng)處于某一個(gè)穩(wěn)定狀態(tài)時(shí),發(fā)生能夠觸發(fā)系統(tǒng)進(jìn)行狀態(tài)切換的事件, 系統(tǒng)去執(zhí)行具體的動(dòng)作來(lái)完成狀態(tài)的切換。
動(dòng)作:系統(tǒng)狀態(tài)變更需要執(zhí)行的具體的操作。
次態(tài):系統(tǒng)完成變更后的狀態(tài)。
綜合上述表示,有限狀態(tài)機(jī)可以表示為五元數(shù)學(xué)符號(hào):
在進(jìn)行理論研究時(shí), 有限狀態(tài)機(jī)一般以數(shù)學(xué)表達(dá)式的方式抽象出來(lái)。 此外,有限狀態(tài)機(jī)還具有狀態(tài)轉(zhuǎn)移圖、轉(zhuǎn)移表和狀態(tài)轉(zhuǎn)移矩陣三種直觀的表示方法。 本文中主要采用狀態(tài)轉(zhuǎn)移圖的表示方法。如圖1 所示,圓圈表示狀態(tài),有向弧線表示狀態(tài)變遷過程,弧線上的字符表示條件,具有開始箭頭標(biāo)注的圓圈表示初始狀態(tài),雙圓圈表示最終狀態(tài)。該表示方法可以直觀的表示系統(tǒng)的狀態(tài)集合、狀態(tài)切換過程以及切換條件。
圖1 有限狀態(tài)機(jī)狀態(tài)轉(zhuǎn)移圖
基于有限狀態(tài)機(jī)的雙機(jī)熱備系統(tǒng)的總體架構(gòu)如圖2 所示,在兩臺(tái)機(jī)器中分別運(yùn)行一套控制系統(tǒng), 包括UI 界面、 應(yīng)用服務(wù)、PostgreSQL、Redis、通訊服務(wù)與熱備服務(wù)。 其中,UI 界面主要是展示展示各模塊的狀態(tài)與操作按鈕; 應(yīng)用服務(wù)主要是用來(lái)獲取PostgreSQL 數(shù)據(jù)庫(kù)、Redis 數(shù)據(jù)庫(kù)、 通訊服務(wù)以及熱備服務(wù)的各模塊的狀態(tài); 熱備服務(wù)主要是用來(lái)監(jiān)測(cè)各服務(wù)的狀態(tài)與控制A機(jī)和B 機(jī)的狀態(tài)切換。
圖2 系統(tǒng)架構(gòu)圖
熱備服務(wù)的內(nèi)部架構(gòu)設(shè)計(jì)為4 個(gè)單元與3 個(gè)外圍受控組件,通過4 個(gè)單元與組件構(gòu)成了完整的熱備服務(wù)。
3.2.1 通信單元
通信單元的設(shè)計(jì)主要是實(shí)現(xiàn)A 機(jī)與B 機(jī)的狀態(tài)信息的交換。 狀態(tài)信息的交換主要是通過keepalived 的vrrp 協(xié)議的報(bào)文處理實(shí)現(xiàn)。
3.2.2 PostgreSQL
PostgreSQL 是實(shí)現(xiàn)終端數(shù)據(jù)與配置數(shù)據(jù)的持久化存儲(chǔ)的數(shù)據(jù)庫(kù)系統(tǒng)。
3.2.3 Redis
Redis 是為減輕PostgreSQL 數(shù)據(jù)庫(kù)的訪問壓力,存放常用讀取數(shù)據(jù)的數(shù)據(jù)庫(kù)系統(tǒng)。
3.2.4 通訊服務(wù)
通訊服務(wù)主要是接收終端的數(shù)據(jù), 并保存至PostgreSQL 數(shù)據(jù)庫(kù),其中工作狀態(tài)包含“ 主模式”與“ 備模式”。
3.2.5 監(jiān)控單元
監(jiān)控單元主要監(jiān)控A 機(jī)與B 機(jī)的狀態(tài),并根據(jù)A 機(jī)與B 機(jī)的狀態(tài)進(jìn)行工作狀態(tài)的遷移, 其中機(jī)器的工作狀態(tài)包含通訊服務(wù)的工作狀態(tài)、PostgreSQL 的工作狀態(tài)與Redis 的工作狀態(tài)。 機(jī)器的狀態(tài)轉(zhuǎn)移,包含遷移狀態(tài)與終態(tài),其中,遷移狀態(tài)包含:待協(xié)商、待確認(rèn)、嘗試進(jìn)入主模式、嘗試進(jìn)入備模式、嘗試提升為主模式,終態(tài)包括:主模式與備模式。 為進(jìn)一步說(shuō)明狀態(tài)遷移的流程,如圖3 所示,為A 機(jī)機(jī)器啟動(dòng)的完整工作流程:
圖3 機(jī)器啟動(dòng)流程圖
其中,條件a:返回的B 機(jī)狀態(tài)未知或未獲取到B 機(jī)的狀態(tài);條件b: 返回的B 機(jī)的狀態(tài)屬于狀態(tài)集2; 條件c: A 機(jī)的PostgreSQL 以備模式啟動(dòng)、Redis 以備模式啟動(dòng)與通訊服務(wù)為備模式; 條件d:A 機(jī)的PostgreSQL 以主模式啟動(dòng)、Redis 以主模式啟動(dòng)與通訊服務(wù)為主模式;條件e:返回的B 機(jī)的狀態(tài)屬于狀態(tài)集1;條件f:返回B 機(jī)的PostgreSQL 數(shù)據(jù)庫(kù)狀態(tài)(某表的數(shù)據(jù)量),確定A 機(jī)的優(yōu)先級(jí)比B 機(jī)的優(yōu)先級(jí)高; 條件g: 返回B 機(jī)的PostgreSQL 數(shù)據(jù)庫(kù)狀態(tài)(某表的數(shù)據(jù)量),確定A 機(jī)的優(yōu)先級(jí)比B機(jī)的優(yōu)先級(jí)低;條件h:A 機(jī)的優(yōu)先級(jí)比B 機(jī)的優(yōu)先級(jí)高;條件i:A 機(jī)的PostgreSQL 以主模式啟動(dòng)、Redis 以主模式啟動(dòng)與通訊服務(wù)為主模式;其中:狀態(tài)集1 包含:“ 協(xié)商”與“ 確認(rèn)”;狀態(tài)集2 包含:“ 嘗試進(jìn)入主模式”、“ 切換為主模式”與“ 主模式”;狀態(tài)集3 包含:“ 嘗試進(jìn)入備模式”與“ 備模式”;初始狀態(tài):“ 協(xié)商”;最終狀態(tài):“ 主模式”與“ 備模式”。
3.2.6 控制單元
控制單元主要是完成機(jī)器狀態(tài)的切換與虛擬IP 的切換,其主要功能是基于keepalived 實(shí)現(xiàn)。 其中,機(jī)器狀態(tài)的切換是通過在keepalived 中定義切換到相應(yīng)模式時(shí)的執(zhí)行腳本來(lái)實(shí)現(xiàn),虛擬IP 的切換通過keepalived 的工作優(yōu)先級(jí)來(lái)確定建立虛擬IP 的機(jī)器。
3.2.7 同步單元
同步的單元包含PostgreSQL 數(shù)據(jù)庫(kù)與Redis 數(shù)據(jù)庫(kù)的數(shù)據(jù)同步。 PostgreSQL 數(shù)據(jù)庫(kù)的同步是基于異步流復(fù)制傳遞預(yù)寫日志的方式來(lái)實(shí)現(xiàn)的。 A 機(jī)與B 機(jī)的PostgreSQL 數(shù)據(jù)庫(kù)在使用流復(fù)制時(shí), 只要處于主模式工作的機(jī)器的PostgreSQL 數(shù)據(jù)庫(kù)一產(chǎn)生日志, 就會(huì)馬上傳遞到處于備模式工作的機(jī)器的PostgreSQL數(shù)據(jù)庫(kù)。 假設(shè)A 機(jī)器原來(lái)工作在主模式,當(dāng)A 機(jī)的數(shù)據(jù)庫(kù)工作異?;蛘弑豢刂茊卧袚Q為備模式工作狀態(tài)時(shí), 機(jī)器B 上以主模式重啟數(shù)據(jù)庫(kù),在數(shù)據(jù)庫(kù)剛重啟時(shí),會(huì)重放B 機(jī)的數(shù)據(jù)庫(kù)狀態(tài)切換之前最后一個(gè)checkpoint 點(diǎn)之后的WAL 日志,把數(shù)據(jù)庫(kù)推導(dǎo)到自動(dòng)進(jìn)入工作狀態(tài), 數(shù)據(jù)庫(kù)在完成恢復(fù)后會(huì)自動(dòng)進(jìn)入正常狀態(tài),此時(shí)的A 機(jī)器在控制單元的協(xié)助下重新啟動(dòng),以備模式啟動(dòng),一直等待A 機(jī)的新的WAL 日志,如果有新的日志過來(lái),則自定進(jìn)行重放,直到A 機(jī)器工作異常,B 機(jī)以主模式狀態(tài)工作,再讓B 機(jī)的數(shù)據(jù)庫(kù)進(jìn)入主模式工作, 實(shí)現(xiàn)了A 機(jī)器上的數(shù)據(jù)庫(kù)出故障時(shí),B 機(jī)器的上的數(shù)據(jù)庫(kù)能夠接管的功能。
Redis 的數(shù)據(jù)同步分為全量同步與增量同步兩個(gè)過程, 其中全量同步主要是指從模式的Redis 數(shù)據(jù)庫(kù)啟動(dòng)的時(shí)候的初始化過程,增量同步指的是主模式的Redis 每執(zhí)行一個(gè)寫命令就像從模式的Redis 發(fā)送相同的寫命令,從模式的Redis 接收并執(zhí)行收到的寫命令。 假設(shè)A 機(jī)的Redis 數(shù)據(jù)庫(kù)以master 模式啟動(dòng),B 機(jī)的Redis 數(shù)據(jù)庫(kù)以slave 模式啟動(dòng), 此時(shí)當(dāng)B 機(jī)的Redis 數(shù)據(jù)庫(kù)在啟動(dòng)的初始化階段需要將A 機(jī)的Redis 數(shù)據(jù)庫(kù)的數(shù)據(jù)全部復(fù)制一遍。 具體步驟如下:a. B 機(jī)的Redis 數(shù)據(jù)庫(kù)連接A 機(jī)的Redis,并發(fā)送同步命令;b. A 機(jī)的Redis 接收到同步命令后,開始執(zhí)行數(shù)據(jù)保存命令, 生成快照文件并使用緩沖區(qū)記錄此后執(zhí)行的所有寫命令;c. A 機(jī)的Redis 數(shù)據(jù)庫(kù)將快照文件發(fā)送至B 機(jī)的Redis 數(shù)據(jù)庫(kù), 并在發(fā)送期間記錄被執(zhí)行的寫命令;d. B 機(jī)的Redis 數(shù)據(jù)庫(kù)接收到快照文件后丟棄所有數(shù)據(jù),載入收到的快照;e. A 機(jī)的Redis 發(fā)送完快照文件,繼續(xù)向B 機(jī)的Redis 發(fā)送緩沖區(qū)的寫命令;f. B 機(jī)的Redis 完成快照文件的載入后, 開始接收命令請(qǐng)求,并持續(xù)接收來(lái)自A 機(jī)的緩沖區(qū)的寫命令。
基于有限狀態(tài)機(jī)機(jī)制的雙機(jī)熱備系統(tǒng)采用傳軟件的方式實(shí)現(xiàn),具有節(jié)約成本與部署方便優(yōu)點(diǎn),并且對(duì)外提供了一系列的信息交互接口, 使得現(xiàn)有的人員定位系統(tǒng)的雙機(jī)熱備運(yùn)行更加簡(jiǎn)單、穩(wěn)定、可靠。