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