高 昕,黃 真
(國電南瑞科技股份有限公司,江蘇南京 210061)
Redis 的全名為遠(yuǎn)程字典服務(wù)(Remote Dictionary Server),它是一個基于內(nèi)存的鍵-值(Key-Value)數(shù)據(jù)庫,在很大程度上彌補(bǔ)了內(nèi)存緩沖存儲的匱乏[1]。Redis 為 Value 提供了非常靈活的數(shù)據(jù)形式,主要包括字符串(String)、鏈表(List)、集合(Set)、有序集合(Zset)及哈希表等[2]。對于不同的存儲需求,Redis 中總可以找到相應(yīng)的鍵-值數(shù)據(jù)類型來匹配,例如將 String與 Json(JavaScript 對象表示法)進(jìn)行結(jié)合,可以將完整的數(shù)據(jù)結(jié)構(gòu)存入值中,而哈希表的方式又為成員變量的快速存取提供了極大的方便。Redis 在將數(shù)據(jù)實時寫入內(nèi)存的同時,可以根據(jù)系統(tǒng)設(shè)計的需要,采用快照存儲(Snapshotting)或附加文件(AOF)的方式將數(shù)據(jù)進(jìn)行持久化[3],一定程度上保證了數(shù)據(jù)安全,防止系統(tǒng)故障等意外事故對重要數(shù)據(jù)的影響。
Redis 支持多個實例的集群,采用一主(Master)多從(Slave)的方式,主/從之間采用數(shù)據(jù)復(fù)制的方式,可以將因單一 Redis 實例故障而導(dǎo)致的數(shù)據(jù)丟失及系統(tǒng)故障的概率降至最低,且結(jié)構(gòu)上支持多級主/從[4]。集群內(nèi)的主/從復(fù)制功能對雙方都不會產(chǎn)生阻塞(圖1),從節(jié)點可以只當(dāng)作主節(jié)點的數(shù)據(jù)冗余備份,也可以提供只讀命令來減輕主節(jié)點服務(wù)器的壓力[5]。
圖1 主/從復(fù)制原理
Redis-Sentinel 是 Redis 官方推薦的高可用性解決方案,其本身也是一個獨(dú)立運(yùn)行的進(jìn)程,它能監(jiān)控多個主/從集群,發(fā)現(xiàn)主節(jié)點宕機(jī)后能進(jìn)行自動切換。主要有以下功能。
(1)監(jiān)控:Sentinel 時刻監(jiān)控 Redis 是否按照預(yù)期良好地運(yùn)行。
(2)提醒:如果發(fā)現(xiàn)某個 Redis 節(jié)點運(yùn)行出現(xiàn)狀況,能夠通知集群中其他 Sentinel 進(jìn)程或應(yīng)用服務(wù)。
(3)自動故障遷移:當(dāng) 1 個主節(jié)點不可用時,能夠從該主節(jié)點的多個從節(jié)點中推選出 1 個可用的升為主節(jié)點,并通知其他從節(jié)點從新的主節(jié)點復(fù)制數(shù)據(jù)。
(4)Sentinel 本身支持集群的方式,對于主/從的切換采用多數(shù)表決的方法進(jìn)行推選。另外,即使并非全部的 Sentinel 都在工作,Sentinel 也可以正常工作。Redis 與Redis-Sentinel 建立的集群結(jié)構(gòu)如圖2 所示。
圖2 Redis 集群框架
Redis 的發(fā)布/訂閱(Pub/Sub)功能類似于以往的消息路由功能,發(fā)布/訂閱模式包含 2 種角色,分別是發(fā)布者和訂閱者。發(fā)布者發(fā)布消息,訂閱者接收消息,而訂閱的頻道則用來溝通發(fā)布者和訂閱者。發(fā)布/訂閱模式可以為進(jìn)程之間提供消息傳遞,訂閱者可以訂閱 1 個或若干個頻道,發(fā)布者可以向任意頻道發(fā)送消息,只要訂閱了此頻道,都將收到此消息[6]。
在 Redis-Sentinel 的集群應(yīng)用中,客戶端通過應(yīng)用程序接口(API)向任一 Sentinel 服務(wù)訂閱主/從切換的通知消息,則當(dāng) Sentinel 監(jiān)測到主節(jié)點或從節(jié)點的任何狀態(tài)變化時(上線、下線、表決結(jié)果及故障切換狀態(tài)等),都將通過消息通道發(fā)送到客戶端,通知客戶端重新連接最新的主/從節(jié)點以進(jìn)行數(shù)據(jù)操作。
與地鐵不同,有軌電車因為自身的特點(與公共交通共享路權(quán)、行駛速度低等)決定了車載系統(tǒng)為非“故障-安全”系統(tǒng)[7]。在該系統(tǒng)中,控制及采集、顯示終端均采用雙機(jī)熱備的方式,分別放置于車廂兩端的駕駛艙中[8]。典型的有軌電車車載系統(tǒng)的組成如圖3 所示。
該系統(tǒng)的組成主要包括以下幾個特點:
(1)2 套冗余的車載控制主機(jī)(OBU)獨(dú)立接收各種外部接口數(shù)據(jù);
(2)數(shù)據(jù)匯集在被接收的 OBU 中,2 套OBU 之間進(jìn)行數(shù)據(jù)交互;
(3)1 套 OBU 故障時,由另外 1 套系統(tǒng)進(jìn)行控制接管。
該系統(tǒng)構(gòu)架對于非“故障-安全”的系統(tǒng)可以滿足系統(tǒng)功能要求,但可能帶來的問題主要有:
(1)2 套 OBU 之間需要在軟件級別同步數(shù)據(jù),如當(dāng)主用機(jī) GPS 接收故障時,備用機(jī)接收到 GPS 位置數(shù)據(jù)時需要與主用機(jī)同步,既要考慮數(shù)據(jù)同步周期等問題,也要定義復(fù)雜的通信接口;
(2)針對每個 OBU 系統(tǒng)來說,接收到的外部數(shù)據(jù)及系統(tǒng)關(guān)鍵數(shù)據(jù)一般被存儲在進(jìn)程自身的內(nèi)存中,關(guān)鍵數(shù)據(jù)的持久化通過應(yīng)用軟件進(jìn)行本地文件的讀寫來完成,當(dāng)系統(tǒng)故障重啟時可能會造成關(guān)鍵數(shù)據(jù)的丟失;
(3)客戶端對數(shù)據(jù)的訪問只能通過向主用 OBU 主動查詢或接收主用 OBU 的數(shù)據(jù)推送而獲得。
綜上列舉的應(yīng)用層的問題,雖然不會對系統(tǒng)安全穩(wěn)定帶來影響,但卻為功能的實現(xiàn)增加了操作復(fù)雜度,同時系統(tǒng)結(jié)構(gòu)中各個模塊之間需要定義非常復(fù)雜的基于網(wǎng)絡(luò)的通信接口,也為系統(tǒng)間模塊增加了很大的耦合性。
圖3 車載系統(tǒng)結(jié)構(gòu)簡圖
基于 Redis 集群的車載系統(tǒng)方案,在系統(tǒng)的結(jié)構(gòu)上帶來的優(yōu)勢主要有:
(1)Redis 是一個開放網(wǎng)絡(luò)訪問的數(shù)據(jù)庫,系統(tǒng)內(nèi)的任意授權(quán)節(jié)點都可以通過相應(yīng)的應(yīng)用程序接口(API)從集群中獲取最新的數(shù)據(jù),在數(shù)據(jù)訪問的隨機(jī)性上十分靈活;
(2)任意的接口程序都可以通過 API 及集群代理軟件將最新的數(shù)據(jù)寫入 Redis,數(shù)據(jù)庫中只保存 1 份最新的數(shù)據(jù),為冗余系統(tǒng)的應(yīng)用層開發(fā)帶來便利;
(3)Redis 系統(tǒng)集群中,主/從的復(fù)制由 Redis 負(fù)責(zé)執(zhí)行,用戶不需要關(guān)心冗余系統(tǒng)中多個數(shù)據(jù)庫數(shù)據(jù)不一致或新上電機(jī)器的數(shù)據(jù)同步問題;
(4)集群系統(tǒng)的穩(wěn)定性不會因為某個客戶端或服務(wù)端的故障而受到影響,且 Redis 的持久化技術(shù)可以將內(nèi)存數(shù)據(jù)按照設(shè)定的方式固化到本地文件中,保證了數(shù)據(jù)的安全性,當(dāng) Redis 故障重啟時,可以從本地文件中重新加載數(shù)據(jù)到內(nèi)存;
(5)Redis 的數(shù)據(jù)訪問十分高效,支持單步、事務(wù)、異步及管道技術(shù)等方法進(jìn)行批量數(shù)據(jù)庫訪問[9]。
由此可見,采用 Redis 集群技術(shù)的車載系統(tǒng)可以為應(yīng)用層的開發(fā)提供極大的便利性和系統(tǒng)數(shù)據(jù)的安全穩(wěn)定性,基于此思路建立的車載系統(tǒng)結(jié)構(gòu)圖如圖4 所示。
分析圖4 的系統(tǒng)結(jié)構(gòu)圖,可知:
(1)字母 A、B 分別代表2 套車載設(shè)備對應(yīng)的實例,每套設(shè)備均配備獨(dú)立的前置接口程序;
(2)2 個以上的 Redis 實例被平分在 2 套車載設(shè)備OBU中,組成 Redis 集群;多個 Redis-Sentinel 實例被平分在 2 套車載設(shè)備 OBU 中,組成 Redis-Sentinel 集群,如圖4 中虛線框部分;
(3)Redis 集群數(shù)據(jù)庫的內(nèi)部主/從關(guān)系由 Sentinel集群表決決定,Redis 集群內(nèi)部提供主/從數(shù)據(jù)復(fù)制及數(shù)據(jù)持久化功能;
(4)Redis 集群內(nèi)的主/從狀態(tài)由 Sentinel 集群進(jìn)行廣播通知,所有集群內(nèi)部 Redis 實例對系統(tǒng)結(jié)構(gòu)內(nèi)元素開放,如智能顯示終端(TOD)可根據(jù) OBU 的主備狀態(tài)及 Redis 集群的主/從關(guān)系,動態(tài)設(shè)定讀訪問實例及寫訪問實例,實行負(fù)載均擔(dān);
(5)在 Redis 集群及應(yīng)用軟件之間添加集群代理層軟件(Redis-Proxy),集群的任何狀態(tài)變化由代理軟件進(jìn)行收集并實時切換讀寫鏈接,同時代理軟件的功能將實現(xiàn)集群的主/從切換對上層應(yīng)用程序透明,通過接口實現(xiàn)對Redis數(shù)據(jù)的讀寫訪問;
(6)2 套系統(tǒng)中任何進(jìn)程的單點故障都不會導(dǎo)致系統(tǒng)的不穩(wěn)定,包括智能顯示終端(TOD)、通信接口、單一的 Redis 庫、單一的 Redis-Sentinel 實例等。
圖4 基于 Redis 集群的車載系統(tǒng)結(jié)構(gòu)
自 Redis 問世以來就以其高效的內(nèi)存訪問速度、靈活的數(shù)據(jù)形式、可靠的數(shù)據(jù)存儲及基于 Web 的訪問方式等優(yōu)點被越來越多的大型互聯(lián)網(wǎng)企業(yè)所應(yīng)用[8],如新浪微博建立了史上最大的 Redis 集群,用于數(shù)據(jù)發(fā)布及存儲,說明 Redis 的強(qiáng)大功能已經(jīng)獲得了互聯(lián)網(wǎng)及數(shù)據(jù)緩存行業(yè)的認(rèn)可。但在城市軌道交通信號領(lǐng)域中,Redis的應(yīng)用則少之又少,一方面是通信信號領(lǐng)域的安全性要求使然,另一方面則是由長久以來信號領(lǐng)域的技術(shù)壟斷造成的。
本文主要結(jié)合江蘇省經(jīng)信委資助項目——“有軌電車運(yùn)行控制系統(tǒng)關(guān)鍵技術(shù)研究”的實施,對自主研發(fā)的有軌電車車載系統(tǒng)中 Redis 的應(yīng)用情況進(jìn)行了簡要描述,證明 Redis 集群在城市軌道交通信號領(lǐng)域的產(chǎn)品研發(fā)及應(yīng)用中是可行的。其實,Redis 功能的強(qiáng)大遠(yuǎn)遠(yuǎn)超過了文中描述的內(nèi)容,還需要在實際使用中對 Redis 集群功能進(jìn)行更加深入的研究與挖掘。
[1]王 如. Redis消息推送機(jī)制應(yīng)用技術(shù)研究[J]. 科技廣場,2016(8):41-44.
[2]曾超宇,李金香. Redis在高速緩存系統(tǒng)中的應(yīng)用[J].微型機(jī)與應(yīng)用,2013,32(12):11-13.
[3]王心 ,毛莉君. 基于Twemproxy的Redis集群解決方案的設(shè)計與實現(xiàn)[J]. 電子測試,2016(6):16-17.
[4]賴 . 基于Redis的分布式鎖的實現(xiàn)方案[J]. 信息通信,2016(10):83-84.
[5]明. 高可用可擴(kuò)展集群化Redis設(shè)計與實現(xiàn)[D]. 陜西西安:西安電子科技大學(xué),2014.
[6]余博,賈利民,秦勇,等. 城軌列車視頻數(shù)據(jù)傳輸系統(tǒng)的設(shè)計與實現(xiàn)[J]. 物流技術(shù),2014,33(2):316-319,383.
[7]明瑞利. 有軌電車系統(tǒng)安全性分析[J]. 城市交通,2016(4):59-63,12.
[8]蔣衛(wèi)中. 軌道交通車載綜合監(jiān)控系統(tǒng)設(shè)計[J]. 都市快軌交通,2012,25(4):116-118,122.
[9]柳 亮,王麗,周陽辰. Redis集群性能測試分析[J].微型機(jī)與應(yīng)用,2016,35(10):70-71,78.