陳汝鵬,焦 楓,張潔心
(1.中通服咨詢設(shè)計(jì)研究院有限公司,江蘇 南京 210019;2.江蘇基久網(wǎng)絡(luò)科技有限公司南京分公司,江蘇 南京 210019)
隨著移動(dòng)互聯(lián)網(wǎng)、物聯(lián)網(wǎng)的發(fā)展,基于SQLite數(shù)據(jù)庫的應(yīng)用越來越多。SQLite為獨(dú)立應(yīng)用和設(shè)備提供本地化存儲,強(qiáng)調(diào)資源節(jié)約、高性能、可靠性、獨(dú)立性以及易用性。SQLite數(shù)據(jù)庫具有簡單、自包含、零配置等特點(diǎn),方便應(yīng)用的開發(fā),用戶只需要在設(shè)備或應(yīng)用所在的服務(wù)器進(jìn)行單配置就能使用一個(gè)功能豐富的關(guān)系型數(shù)據(jù)庫,尤其適用于嵌入式應(yīng)用。隨著業(yè)務(wù)的擴(kuò)大,每套設(shè)備或應(yīng)用自帶一個(gè)SQLite數(shù)據(jù)庫,運(yùn)營人員很難擁有一個(gè)集所有設(shè)備數(shù)據(jù)于一體的全集數(shù)據(jù)庫,這就產(chǎn)生了SQLite數(shù)據(jù)庫實(shí)時(shí)同步到遠(yuǎn)程數(shù)據(jù)庫的需求[1-3]。本文針對SQLite的特點(diǎn)與需求,討論了基于文件探測的SQLite多源遠(yuǎn)程實(shí)時(shí)數(shù)據(jù)同步的實(shí)現(xiàn)方法。
SQLite是一個(gè)本地?cái)?shù)據(jù)庫,它可以將數(shù)據(jù)庫的所有表、索引、視圖等存儲到一個(gè)單獨(dú)的文件里。它具有以下特性:①滿足數(shù)據(jù)庫事務(wù)的原則性、一致性、隔離性以及持久性的特點(diǎn),即使在系統(tǒng)崩潰和電源故障后,數(shù)據(jù)庫也能保持與故障前的事務(wù)一致性;②零配置,無需設(shè)置或管理;③SQLite數(shù)據(jù)庫輕量,但是包含了標(biāo)準(zhǔn)SQL的全部功能實(shí)現(xiàn),例如索引、公共表達(dá)式和窗口函數(shù)等;④單文件,單個(gè)跨平臺磁盤文件即可存儲完整的數(shù)據(jù)庫;⑤支持Blob,數(shù)據(jù)庫的存儲支持千兆字節(jié)大小的字符串和Blob類型的字段;⑥應(yīng)用程序接口(Application Program Interface,API)簡單易用;⑦良好的擴(kuò)展性,使用ANSI-C編寫,支持多種其他語言的對接使用;⑧自包含,無外部依賴關(guān)系;⑨跨平臺,支持Android、iOS、Linux,Mac、Solaris、VxWorks以及Windows,易于移植到其他系統(tǒng)[4]。
關(guān)系型數(shù)據(jù)庫引擎實(shí)現(xiàn)企業(yè)級數(shù)據(jù)共享,強(qiáng)調(diào)數(shù)據(jù)的可伸縮性、并發(fā)性、中心性以及控制性。SQLite為獨(dú)立應(yīng)用和設(shè)備提供本地化存儲,強(qiáng)調(diào)資源節(jié)約、高性能、可靠性、獨(dú)立性以及易用性[5]。關(guān)系型數(shù)據(jù)庫主要用于高并發(fā)、數(shù)據(jù)量相對較大、通過網(wǎng)絡(luò)與應(yīng)用程序分離的場景;而SQLite數(shù)據(jù)庫由于其簡單、靈活、高效的特點(diǎn),能夠適用于許多其他的場景[6]。
(1)嵌入式設(shè)備和物聯(lián)網(wǎng)。基于SQLite數(shù)據(jù)庫零配置的特點(diǎn),該數(shù)據(jù)庫的應(yīng)用不需要數(shù)據(jù)庫管理員的運(yùn)營維護(hù),因此在嵌入式應(yīng)用中廣泛流行,包括移動(dòng)電話、機(jī)頂盒、電視機(jī)、游戲控制器、攝像機(jī)、智能手表、廚房電器、恒溫控制器、汽車、機(jī)床、飛機(jī)、遙控器、遙控飛機(jī)、醫(yī)療器械以及機(jī)器人等[7]。
(2)應(yīng)用程序文件。SQLite經(jīng)常被用來存放一些應(yīng)用程序的過程數(shù)據(jù),例如版本控制系統(tǒng)、金融分析工具、剪輯套件的媒體目錄以及CAD文件包等。當(dāng)應(yīng)用程序修改內(nèi)容時(shí),數(shù)據(jù)庫會自動(dòng)更新。
(3)網(wǎng)站。由于SQLite輕量、方便,因此在小、中型流量的網(wǎng)站(絕大部分網(wǎng)站)中很流行。
(4)數(shù)據(jù)分析。SQLite可以用于網(wǎng)站訪問日志分析、體育統(tǒng)計(jì)分析、實(shí)驗(yàn)結(jié)果分析等。
(5)企業(yè)數(shù)據(jù)緩存。由于大部分查詢在本地進(jìn)行,因此可以從關(guān)系型數(shù)據(jù)庫中緩存一部分?jǐn)?shù)據(jù)到本地(存儲到SQLite中),從而減少延遲,避免網(wǎng)絡(luò)的雙向損耗,減少網(wǎng)絡(luò)的負(fù)載[8]。
(6)服務(wù)器端數(shù)據(jù)庫。SQLite可以給客戶端提供數(shù)據(jù),類似于C/S架構(gòu),此應(yīng)用場景與關(guān)系型數(shù)據(jù)庫類似。
(7)數(shù)據(jù)傳送。由于SQLite是單文件數(shù)據(jù)庫,而且文件格式兼容各個(gè)操作系統(tǒng)平臺,因此經(jīng)常被用來作為數(shù)據(jù)傳輸?shù)拿浇椤0l(fā)送者只需要將數(shù)據(jù)導(dǎo)出到一個(gè)SQLite文件并將此文件傳送給接收者,接收者用SQL提取需要的數(shù)據(jù)即可。
(8)文件歸檔/數(shù)據(jù)容器。將文件內(nèi)容打包進(jìn)SQLite數(shù)據(jù)庫,類似于通過ZIP壓縮文件,其優(yōu)點(diǎn)是能實(shí)時(shí)更新。
生產(chǎn)經(jīng)營活動(dòng)中,SQLite數(shù)據(jù)庫經(jīng)常被用于嵌入式設(shè)備中。嵌入式設(shè)備作為單體應(yīng)用,其實(shí)現(xiàn)的業(yè)務(wù)和功能是自包含的,一般不需要遠(yuǎn)程或云上的服務(wù)支持,甚至不需要接入局域網(wǎng),因此很容易推廣與應(yīng)用。隨著生產(chǎn)經(jīng)營活動(dòng)的不斷開展,如果管理人員需要采集嵌入式設(shè)備的運(yùn)行信息,如此多且分散的SQLite數(shù)據(jù)庫與遠(yuǎn)程中心數(shù)據(jù)庫進(jìn)行數(shù)據(jù)同步將會非常復(fù)雜。如果每個(gè)單體應(yīng)用直接與中心數(shù)據(jù)庫進(jìn)行連接,則對中心數(shù)據(jù)庫的承載能力要求非常高,且這樣的連接數(shù)是在不斷增長的[9]。SQLite單體應(yīng)用與中心數(shù)據(jù)庫拓?fù)淙鐖D1所示。

圖1 SQLite單體應(yīng)用與中心數(shù)據(jù)庫拓?fù)?/p>
嵌入式設(shè)備等單體應(yīng)用在生產(chǎn)經(jīng)營環(huán)境中往往是獨(dú)立的存在,部署調(diào)試之后運(yùn)行了很長時(shí)間,對其進(jìn)行改造的難度比較大,因此需要在不影響原有程序正常運(yùn)行的情況下,將運(yùn)行數(shù)據(jù)發(fā)送至中心數(shù)據(jù)庫。實(shí)際上,修改生產(chǎn)環(huán)境的應(yīng)用本身難度很大,且會造成不可知的風(fēng)險(xiǎn)[10]。
基于SQLite數(shù)據(jù)庫的應(yīng)用場景一般都是小型項(xiàng)目,實(shí)時(shí)增量同步解決方案較少。實(shí)時(shí)同步的實(shí)現(xiàn)方式一般都是縮短定時(shí)同步任務(wù)的時(shí)間間隔來達(dá)到偽實(shí)時(shí),這種方式通過定時(shí)任務(wù)去查詢數(shù)據(jù)并進(jìn)行比對查看是否有增量數(shù)據(jù),然后取出增量數(shù)據(jù)并發(fā)送給服務(wù)器。通過定時(shí)任務(wù)進(jìn)行數(shù)據(jù)同步是一種低效的試錯(cuò)同步模式,當(dāng)一輪定時(shí)任務(wù)執(zhí)行時(shí)查不到增量數(shù)據(jù),就會造成程序的無效執(zhí)行,給應(yīng)用所在服務(wù)器帶來了很多不必要的開銷。
通過對SQLite的特性、使用場景以及SQLite多源遠(yuǎn)程實(shí)時(shí)數(shù)據(jù)同步的難點(diǎn)的闡述可知,SQLite遠(yuǎn)程增量數(shù)據(jù)實(shí)時(shí)同步需要實(shí)現(xiàn)無侵入式的數(shù)據(jù)采集、存儲。數(shù)據(jù)采集程序監(jiān)聽SQLite數(shù)據(jù)庫單文件,通過消息隊(duì)列實(shí)現(xiàn)SQLite單體應(yīng)用服務(wù)端程序的解耦,數(shù)據(jù)的采集、發(fā)送等不會影響原有應(yīng)用的運(yùn)行,在原有程序幾乎無感知的情況下實(shí)現(xiàn)數(shù)據(jù)同步。本解決方案的網(wǎng)絡(luò)拓?fù)淙鐖D2所示。

圖2 網(wǎng)絡(luò)拓?fù)?/p>
本解決方案的原理主要是通過監(jiān)聽SQLite數(shù)據(jù)庫單文件的改變,從而監(jiān)測到SQLite數(shù)據(jù)庫發(fā)生了修改操作,包括數(shù)據(jù)的新增、修改和刪除,以此獲得數(shù)據(jù)發(fā)生改變的實(shí)時(shí)時(shí)間點(diǎn)。在這個(gè)時(shí)間點(diǎn)去查詢增量數(shù)據(jù),并將增量數(shù)據(jù)發(fā)送到消息隊(duì)列,服務(wù)端程序從消息隊(duì)列取出數(shù)據(jù)并解析入庫,實(shí)現(xiàn)了SQLite遠(yuǎn)程數(shù)據(jù)實(shí)時(shí)增量同步。整個(gè)過程通過SQLite數(shù)據(jù)庫文件發(fā)生改變這一事件進(jìn)行驅(qū)動(dòng),并通過消息隊(duì)列進(jìn)行解耦,解決了數(shù)據(jù)的實(shí)時(shí)性以及操作無侵入的問題。整個(gè)過程的流程如圖3所示。

圖3 功能流程
本解決方案由采集程序、消息傳輸通道以及服務(wù)端程序組成。采集程序通常與基于SQLite數(shù)據(jù)庫的應(yīng)用程序部署在同一臺設(shè)備上,是本解決方案的核心部分。采集程序通過監(jiān)聽SQLite數(shù)據(jù)庫的文件,捕獲數(shù)據(jù)庫文件發(fā)生改變的時(shí)間點(diǎn),然后通過觸發(fā)器方式或時(shí)間戳方式查詢得到增量數(shù)據(jù),按照約定的統(tǒng)一數(shù)據(jù)格式進(jìn)行打包,并發(fā)送到消息傳輸通道。消息傳輸通道部署了消息隊(duì)列,接收采集程序發(fā)送過來的增量數(shù)據(jù),并提供給服務(wù)端程序。消息傳輸通道本身不設(shè)置持久化功能,避免數(shù)據(jù)被泄露。服務(wù)端程序訂閱消息傳輸通道中的消息隊(duì)列,當(dāng)消息傳輸通道中有新的數(shù)據(jù)時(shí)會將其推送到服務(wù)端程序的數(shù)據(jù)解析模塊,數(shù)據(jù)解析模塊按照約定的數(shù)據(jù)格式進(jìn)行解析入庫。
下面針對SQLite數(shù)據(jù)庫文件監(jiān)聽、增量數(shù)據(jù)的獲取、數(shù)據(jù)格式約定等介紹本解決方案。
本方案通過 Apache Commons IO 實(shí)現(xiàn)文件的監(jiān)聽,原理是通過另起一個(gè)線程按照固定頻率掃描目錄。通過FileAlterationMoniter啟動(dòng)監(jiān)聽線程、FileAlterationObserver選擇需要監(jiān)聽的目錄、重寫FileAlterationListenerAdaptor的方法可以實(shí)現(xiàn)增量數(shù)據(jù)查詢、發(fā)送的業(yè)務(wù),下面是其中的部分代碼:
File configFile = new File(filePath);
// 因?yàn)楸O(jiān)聽是以目錄為單位進(jìn)行的,所以這里直接獲取文件的根目錄
File dir = configFile.getParentFile();

本方案采用兩種比較成熟的增量數(shù)據(jù)獲取方法,即觸發(fā)器與時(shí)間戳,實(shí)際使用中根據(jù)條件二選一即可。觸發(fā)器方式適用于源表沒有維護(hù)時(shí)間戳字段,程序無法直接獲取到增量數(shù)據(jù),且采集程序有權(quán)限為源數(shù)據(jù)庫創(chuàng)建觸發(fā)器。時(shí)間戳方式適用于應(yīng)用程序本身維護(hù)了時(shí)間戳字段,應(yīng)用本身對源表的新增、修改以及邏輯刪除的同時(shí)會更新時(shí)間戳字段,采集程序通過比較時(shí)間戳字段的值即可獲取增量數(shù)據(jù)。下面舉例說明SQLite數(shù)據(jù)庫觸發(fā)器的創(chuàng)建。
新增操作的觸發(fā)器:


為確保采集端與服務(wù)端對數(shù)據(jù)的一致理解,數(shù)據(jù)格式約定如下:


服務(wù)端根據(jù)此數(shù)據(jù)格式,確定數(shù)據(jù)同步的目的表、表中主鍵以及各個(gè)字段的名稱和值等信息。
SQLite數(shù)據(jù)庫基于其本身簡單易用等特點(diǎn)已經(jīng)在各個(gè)領(lǐng)域得到了廣泛的應(yīng)用,但目前絕大部分基于SQLite數(shù)據(jù)庫的應(yīng)用都是單機(jī)版,數(shù)據(jù)遠(yuǎn)程實(shí)時(shí)增量同步非常困難。本文通過引入采集程序、消息傳輸通道、服務(wù)端程序的集成解決方案,實(shí)現(xiàn)了基于文件探測的SQLite數(shù)據(jù)庫遠(yuǎn)程實(shí)時(shí)增量同步。此方案通過采集程序、消息傳輸通道以及服務(wù)端程序這3層的劃分,采集程序與服務(wù)端程序都只依賴于公網(wǎng)的消息傳輸通道,采集程序與服務(wù)端程序本身相互獨(dú)立,通過約定的數(shù)據(jù)格式實(shí)現(xiàn)數(shù)據(jù)的打包與解析。本解決方案不限定服務(wù)端程序所用的數(shù)據(jù)庫,可以是SQLite數(shù)據(jù)庫、關(guān)系型數(shù)據(jù)庫或者大數(shù)據(jù)類型的數(shù)據(jù)庫。基于文件探測的方式是本解決方案實(shí)現(xiàn)數(shù)據(jù)實(shí)時(shí)同步的基礎(chǔ),此方法避免了通過傳統(tǒng)的定時(shí)任務(wù)周期性查詢數(shù)據(jù)庫帶來的資源開銷,不過對于非采集目標(biāo)的數(shù)據(jù)的改動(dòng)也會觸發(fā)后續(xù)的增量數(shù)據(jù)查詢,造成程序無效執(zhí)行。因此,本方案適用于同步源數(shù)據(jù)庫中的熱點(diǎn)數(shù)據(jù)。