陳汝鵬,焦 楓,張潔心
(1.中通服咨詢設計研究院有限公司,江蘇 南京 210019;2.江蘇基久網(wǎng)絡科技有限公司南京分公司,江蘇 南京 210019)
隨著移動互聯(lián)網(wǎng)、物聯(lián)網(wǎng)的發(fā)展,基于SQLite數(shù)據(jù)庫的應用越來越多。SQLite為獨立應用和設備提供本地化存儲,強調(diào)資源節(jié)約、高性能、可靠性、獨立性以及易用性。SQLite數(shù)據(jù)庫具有簡單、自包含、零配置等特點,方便應用的開發(fā),用戶只需要在設備或應用所在的服務器進行單配置就能使用一個功能豐富的關系型數(shù)據(jù)庫,尤其適用于嵌入式應用。隨著業(yè)務的擴大,每套設備或應用自帶一個SQLite數(shù)據(jù)庫,運營人員很難擁有一個集所有設備數(shù)據(jù)于一體的全集數(shù)據(jù)庫,這就產(chǎn)生了SQLite數(shù)據(jù)庫實時同步到遠程數(shù)據(jù)庫的需求[1-3]。本文針對SQLite的特點與需求,討論了基于文件探測的SQLite多源遠程實時數(shù)據(jù)同步的實現(xiàn)方法。
SQLite是一個本地數(shù)據(jù)庫,它可以將數(shù)據(jù)庫的所有表、索引、視圖等存儲到一個單獨的文件里。它具有以下特性:①滿足數(shù)據(jù)庫事務的原則性、一致性、隔離性以及持久性的特點,即使在系統(tǒng)崩潰和電源故障后,數(shù)據(jù)庫也能保持與故障前的事務一致性;②零配置,無需設置或管理;③SQLite數(shù)據(jù)庫輕量,但是包含了標準SQL的全部功能實現(xiàn),例如索引、公共表達式和窗口函數(shù)等;④單文件,單個跨平臺磁盤文件即可存儲完整的數(shù)據(jù)庫;⑤支持Blob,數(shù)據(jù)庫的存儲支持千兆字節(jié)大小的字符串和Blob類型的字段;⑥應用程序接口(Application Program Interface,API)簡單易用;⑦良好的擴展性,使用ANSI-C編寫,支持多種其他語言的對接使用;⑧自包含,無外部依賴關系;⑨跨平臺,支持Android、iOS、Linux,Mac、Solaris、VxWorks以及Windows,易于移植到其他系統(tǒng)[4]。
關系型數(shù)據(jù)庫引擎實現(xiàn)企業(yè)級數(shù)據(jù)共享,強調(diào)數(shù)據(jù)的可伸縮性、并發(fā)性、中心性以及控制性。SQLite為獨立應用和設備提供本地化存儲,強調(diào)資源節(jié)約、高性能、可靠性、獨立性以及易用性[5]。關系型數(shù)據(jù)庫主要用于高并發(fā)、數(shù)據(jù)量相對較大、通過網(wǎng)絡與應用程序分離的場景;而SQLite數(shù)據(jù)庫由于其簡單、靈活、高效的特點,能夠適用于許多其他的場景[6]。
(1)嵌入式設備和物聯(lián)網(wǎng)?;赟QLite數(shù)據(jù)庫零配置的特點,該數(shù)據(jù)庫的應用不需要數(shù)據(jù)庫管理員的運營維護,因此在嵌入式應用中廣泛流行,包括移動電話、機頂盒、電視機、游戲控制器、攝像機、智能手表、廚房電器、恒溫控制器、汽車、機床、飛機、遙控器、遙控飛機、醫(yī)療器械以及機器人等[7]。
(2)應用程序文件。SQLite經(jīng)常被用來存放一些應用程序的過程數(shù)據(jù),例如版本控制系統(tǒng)、金融分析工具、剪輯套件的媒體目錄以及CAD文件包等。當應用程序修改內(nèi)容時,數(shù)據(jù)庫會自動更新。
(3)網(wǎng)站。由于SQLite輕量、方便,因此在小、中型流量的網(wǎng)站(絕大部分網(wǎng)站)中很流行。
(4)數(shù)據(jù)分析。SQLite可以用于網(wǎng)站訪問日志分析、體育統(tǒng)計分析、實驗結(jié)果分析等。
(5)企業(yè)數(shù)據(jù)緩存。由于大部分查詢在本地進行,因此可以從關系型數(shù)據(jù)庫中緩存一部分數(shù)據(jù)到本地(存儲到SQLite中),從而減少延遲,避免網(wǎng)絡的雙向損耗,減少網(wǎng)絡的負載[8]。
(6)服務器端數(shù)據(jù)庫。SQLite可以給客戶端提供數(shù)據(jù),類似于C/S架構(gòu),此應用場景與關系型數(shù)據(jù)庫類似。
(7)數(shù)據(jù)傳送。由于SQLite是單文件數(shù)據(jù)庫,而且文件格式兼容各個操作系統(tǒng)平臺,因此經(jīng)常被用來作為數(shù)據(jù)傳輸?shù)拿浇椤0l(fā)送者只需要將數(shù)據(jù)導出到一個SQLite文件并將此文件傳送給接收者,接收者用SQL提取需要的數(shù)據(jù)即可。
(8)文件歸檔/數(shù)據(jù)容器。將文件內(nèi)容打包進SQLite數(shù)據(jù)庫,類似于通過ZIP壓縮文件,其優(yōu)點是能實時更新。
生產(chǎn)經(jīng)營活動中,SQLite數(shù)據(jù)庫經(jīng)常被用于嵌入式設備中。嵌入式設備作為單體應用,其實現(xiàn)的業(yè)務和功能是自包含的,一般不需要遠程或云上的服務支持,甚至不需要接入局域網(wǎng),因此很容易推廣與應用。隨著生產(chǎn)經(jīng)營活動的不斷開展,如果管理人員需要采集嵌入式設備的運行信息,如此多且分散的SQLite數(shù)據(jù)庫與遠程中心數(shù)據(jù)庫進行數(shù)據(jù)同步將會非常復雜。如果每個單體應用直接與中心數(shù)據(jù)庫進行連接,則對中心數(shù)據(jù)庫的承載能力要求非常高,且這樣的連接數(shù)是在不斷增長的[9]。SQLite單體應用與中心數(shù)據(jù)庫拓撲如圖1所示。
圖1 SQLite單體應用與中心數(shù)據(jù)庫拓撲
嵌入式設備等單體應用在生產(chǎn)經(jīng)營環(huán)境中往往是獨立的存在,部署調(diào)試之后運行了很長時間,對其進行改造的難度比較大,因此需要在不影響原有程序正常運行的情況下,將運行數(shù)據(jù)發(fā)送至中心數(shù)據(jù)庫。實際上,修改生產(chǎn)環(huán)境的應用本身難度很大,且會造成不可知的風險[10]。
基于SQLite數(shù)據(jù)庫的應用場景一般都是小型項目,實時增量同步解決方案較少。實時同步的實現(xiàn)方式一般都是縮短定時同步任務的時間間隔來達到偽實時,這種方式通過定時任務去查詢數(shù)據(jù)并進行比對查看是否有增量數(shù)據(jù),然后取出增量數(shù)據(jù)并發(fā)送給服務器。通過定時任務進行數(shù)據(jù)同步是一種低效的試錯同步模式,當一輪定時任務執(zhí)行時查不到增量數(shù)據(jù),就會造成程序的無效執(zhí)行,給應用所在服務器帶來了很多不必要的開銷。
通過對SQLite的特性、使用場景以及SQLite多源遠程實時數(shù)據(jù)同步的難點的闡述可知,SQLite遠程增量數(shù)據(jù)實時同步需要實現(xiàn)無侵入式的數(shù)據(jù)采集、存儲。數(shù)據(jù)采集程序監(jiān)聽SQLite數(shù)據(jù)庫單文件,通過消息隊列實現(xiàn)SQLite單體應用服務端程序的解耦,數(shù)據(jù)的采集、發(fā)送等不會影響原有應用的運行,在原有程序幾乎無感知的情況下實現(xiàn)數(shù)據(jù)同步。本解決方案的網(wǎng)絡拓撲如圖2所示。
圖2 網(wǎng)絡拓撲
本解決方案的原理主要是通過監(jiān)聽SQLite數(shù)據(jù)庫單文件的改變,從而監(jiān)測到SQLite數(shù)據(jù)庫發(fā)生了修改操作,包括數(shù)據(jù)的新增、修改和刪除,以此獲得數(shù)據(jù)發(fā)生改變的實時時間點。在這個時間點去查詢增量數(shù)據(jù),并將增量數(shù)據(jù)發(fā)送到消息隊列,服務端程序從消息隊列取出數(shù)據(jù)并解析入庫,實現(xiàn)了SQLite遠程數(shù)據(jù)實時增量同步。整個過程通過SQLite數(shù)據(jù)庫文件發(fā)生改變這一事件進行驅(qū)動,并通過消息隊列進行解耦,解決了數(shù)據(jù)的實時性以及操作無侵入的問題。整個過程的流程如圖3所示。
圖3 功能流程
本解決方案由采集程序、消息傳輸通道以及服務端程序組成。采集程序通常與基于SQLite數(shù)據(jù)庫的應用程序部署在同一臺設備上,是本解決方案的核心部分。采集程序通過監(jiān)聽SQLite數(shù)據(jù)庫的文件,捕獲數(shù)據(jù)庫文件發(fā)生改變的時間點,然后通過觸發(fā)器方式或時間戳方式查詢得到增量數(shù)據(jù),按照約定的統(tǒng)一數(shù)據(jù)格式進行打包,并發(fā)送到消息傳輸通道。消息傳輸通道部署了消息隊列,接收采集程序發(fā)送過來的增量數(shù)據(jù),并提供給服務端程序。消息傳輸通道本身不設置持久化功能,避免數(shù)據(jù)被泄露。服務端程序訂閱消息傳輸通道中的消息隊列,當消息傳輸通道中有新的數(shù)據(jù)時會將其推送到服務端程序的數(shù)據(jù)解析模塊,數(shù)據(jù)解析模塊按照約定的數(shù)據(jù)格式進行解析入庫。
下面針對SQLite數(shù)據(jù)庫文件監(jiān)聽、增量數(shù)據(jù)的獲取、數(shù)據(jù)格式約定等介紹本解決方案。
本方案通過 Apache Commons IO 實現(xiàn)文件的監(jiān)聽,原理是通過另起一個線程按照固定頻率掃描目錄。通過FileAlterationMoniter啟動監(jiān)聽線程、FileAlterationObserver選擇需要監(jiān)聽的目錄、重寫FileAlterationListenerAdaptor的方法可以實現(xiàn)增量數(shù)據(jù)查詢、發(fā)送的業(yè)務,下面是其中的部分代碼:
File configFile = new File(filePath);
// 因為監(jiān)聽是以目錄為單位進行的,所以這里直接獲取文件的根目錄
File dir = configFile.getParentFile();
本方案采用兩種比較成熟的增量數(shù)據(jù)獲取方法,即觸發(fā)器與時間戳,實際使用中根據(jù)條件二選一即可。觸發(fā)器方式適用于源表沒有維護時間戳字段,程序無法直接獲取到增量數(shù)據(jù),且采集程序有權(quán)限為源數(shù)據(jù)庫創(chuàng)建觸發(fā)器。時間戳方式適用于應用程序本身維護了時間戳字段,應用本身對源表的新增、修改以及邏輯刪除的同時會更新時間戳字段,采集程序通過比較時間戳字段的值即可獲取增量數(shù)據(jù)。下面舉例說明SQLite數(shù)據(jù)庫觸發(fā)器的創(chuàng)建。
新增操作的觸發(fā)器:
為確保采集端與服務端對數(shù)據(jù)的一致理解,數(shù)據(jù)格式約定如下:
服務端根據(jù)此數(shù)據(jù)格式,確定數(shù)據(jù)同步的目的表、表中主鍵以及各個字段的名稱和值等信息。
SQLite數(shù)據(jù)庫基于其本身簡單易用等特點已經(jīng)在各個領域得到了廣泛的應用,但目前絕大部分基于SQLite數(shù)據(jù)庫的應用都是單機版,數(shù)據(jù)遠程實時增量同步非常困難。本文通過引入采集程序、消息傳輸通道、服務端程序的集成解決方案,實現(xiàn)了基于文件探測的SQLite數(shù)據(jù)庫遠程實時增量同步。此方案通過采集程序、消息傳輸通道以及服務端程序這3層的劃分,采集程序與服務端程序都只依賴于公網(wǎng)的消息傳輸通道,采集程序與服務端程序本身相互獨立,通過約定的數(shù)據(jù)格式實現(xiàn)數(shù)據(jù)的打包與解析。本解決方案不限定服務端程序所用的數(shù)據(jù)庫,可以是SQLite數(shù)據(jù)庫、關系型數(shù)據(jù)庫或者大數(shù)據(jù)類型的數(shù)據(jù)庫?;谖募綔y的方式是本解決方案實現(xiàn)數(shù)據(jù)實時同步的基礎,此方法避免了通過傳統(tǒng)的定時任務周期性查詢數(shù)據(jù)庫帶來的資源開銷,不過對于非采集目標的數(shù)據(jù)的改動也會觸發(fā)后續(xù)的增量數(shù)據(jù)查詢,造成程序無效執(zhí)行。因此,本方案適用于同步源數(shù)據(jù)庫中的熱點數(shù)據(jù)。