陈汝鹏,焦 枫,张洁心
(1.中通服咨询设计研究院有限公司,江苏 南京 210019;2.江苏基久网络科技有限公司南京分公司,江苏 南京 210019)
随着移动互联网、物联网的发展,基于SQLite数据库的应用越来越多。SQLite为独立应用和设备提供本地化存储,强调资源节约、高性能、可靠性、独立性以及易用性。SQLite数据库具有简单、自包含、零配置等特点,方便应用的开发,用户只需要在设备或应用所在的服务器进行单配置就能使用一个功能丰富的关系型数据库,尤其适用于嵌入式应用。随着业务的扩大,每套设备或应用自带一个SQLite数据库,运营人员很难拥有一个集所有设备数据于一体的全集数据库,这就产生了SQLite数据库实时同步到远程数据库的需求[1-3]。本文针对SQLite的特点与需求,讨论了基于文件探测的SQLite多源远程实时数据同步的实现方法。
SQLite是一个本地数据库,它可以将数据库的所有表、索引、视图等存储到一个单独的文件里。它具有以下特性:①满足数据库事务的原则性、一致性、隔离性以及持久性的特点,即使在系统崩溃和电源故障后,数据库也能保持与故障前的事务一致性;②零配置,无需设置或管理;③SQLite数据库轻量,但是包含了标准SQL的全部功能实现,例如索引、公共表达式和窗口函数等;④单文件,单个跨平台磁盘文件即可存储完整的数据库;⑤支持Blob,数据库的存储支持千兆字节大小的字符串和Blob类型的字段;⑥应用程序接口(Application Program Interface,API)简单易用;⑦良好的扩展性,使用ANSI-C编写,支持多种其他语言的对接使用;⑧自包含,无外部依赖关系;⑨跨平台,支持Android、iOS、Linux,Mac、Solaris、VxWorks以及Windows,易于移植到其他系统[4]。
关系型数据库引擎实现企业级数据共享,强调数据的可伸缩性、并发性、中心性以及控制性。SQLite为独立应用和设备提供本地化存储,强调资源节约、高性能、可靠性、独立性以及易用性[5]。关系型数据库主要用于高并发、数据量相对较大、通过网络与应用程序分离的场景;而SQLite数据库由于其简单、灵活、高效的特点,能够适用于许多其他的场景[6]。
(1)嵌入式设备和物联网。基于SQLite数据库零配置的特点,该数据库的应用不需要数据库管理员的运营维护,因此在嵌入式应用中广泛流行,包括移动电话、机顶盒、电视机、游戏控制器、摄像机、智能手表、厨房电器、恒温控制器、汽车、机床、飞机、遥控器、遥控飞机、医疗器械以及机器人等[7]。
(2)应用程序文件。SQLite经常被用来存放一些应用程序的过程数据,例如版本控制系统、金融分析工具、剪辑套件的媒体目录以及CAD文件包等。当应用程序修改内容时,数据库会自动更新。
(3)网站。由于SQLite轻量、方便,因此在小、中型流量的网站(绝大部分网站)中很流行。
(4)数据分析。SQLite可以用于网站访问日志分析、体育统计分析、实验结果分析等。
(5)企业数据缓存。由于大部分查询在本地进行,因此可以从关系型数据库中缓存一部分数据到本地(存储到SQLite中),从而减少延迟,避免网络的双向损耗,减少网络的负载[8]。
(6)服务器端数据库。SQLite可以给客户端提供数据,类似于C/S架构,此应用场景与关系型数据库类似。
(7)数据传送。由于SQLite是单文件数据库,而且文件格式兼容各个操作系统平台,因此经常被用来作为数据传输的媒介。发送者只需要将数据导出到一个SQLite文件并将此文件传送给接收者,接收者用SQL提取需要的数据即可。
(8)文件归档/数据容器。将文件内容打包进SQLite数据库,类似于通过ZIP压缩文件,其优点是能实时更新。
生产经营活动中,SQLite数据库经常被用于嵌入式设备中。嵌入式设备作为单体应用,其实现的业务和功能是自包含的,一般不需要远程或云上的服务支持,甚至不需要接入局域网,因此很容易推广与应用。随着生产经营活动的不断开展,如果管理人员需要采集嵌入式设备的运行信息,如此多且分散的SQLite数据库与远程中心数据库进行数据同步将会非常复杂。如果每个单体应用直接与中心数据库进行连接,则对中心数据库的承载能力要求非常高,且这样的连接数是在不断增长的[9]。SQLite单体应用与中心数据库拓扑如图1所示。
图1 SQLite单体应用与中心数据库拓扑
嵌入式设备等单体应用在生产经营环境中往往是独立的存在,部署调试之后运行了很长时间,对其进行改造的难度比较大,因此需要在不影响原有程序正常运行的情况下,将运行数据发送至中心数据库。实际上,修改生产环境的应用本身难度很大,且会造成不可知的风险[10]。
基于SQLite数据库的应用场景一般都是小型项目,实时增量同步解决方案较少。实时同步的实现方式一般都是缩短定时同步任务的时间间隔来达到伪实时,这种方式通过定时任务去查询数据并进行比对查看是否有增量数据,然后取出增量数据并发送给服务器。通过定时任务进行数据同步是一种低效的试错同步模式,当一轮定时任务执行时查不到增量数据,就会造成程序的无效执行,给应用所在服务器带来了很多不必要的开销。
通过对SQLite的特性、使用场景以及SQLite多源远程实时数据同步的难点的阐述可知,SQLite远程增量数据实时同步需要实现无侵入式的数据采集、存储。数据采集程序监听SQLite数据库单文件,通过消息队列实现SQLite单体应用服务端程序的解耦,数据的采集、发送等不会影响原有应用的运行,在原有程序几乎无感知的情况下实现数据同步。本解决方案的网络拓扑如图2所示。
图2 网络拓扑
本解决方案的原理主要是通过监听SQLite数据库单文件的改变,从而监测到SQLite数据库发生了修改操作,包括数据的新增、修改和删除,以此获得数据发生改变的实时时间点。在这个时间点去查询增量数据,并将增量数据发送到消息队列,服务端程序从消息队列取出数据并解析入库,实现了SQLite远程数据实时增量同步。整个过程通过SQLite数据库文件发生改变这一事件进行驱动,并通过消息队列进行解耦,解决了数据的实时性以及操作无侵入的问题。整个过程的流程如图3所示。
图3 功能流程
本解决方案由采集程序、消息传输通道以及服务端程序组成。采集程序通常与基于SQLite数据库的应用程序部署在同一台设备上,是本解决方案的核心部分。采集程序通过监听SQLite数据库的文件,捕获数据库文件发生改变的时间点,然后通过触发器方式或时间戳方式查询得到增量数据,按照约定的统一数据格式进行打包,并发送到消息传输通道。消息传输通道部署了消息队列,接收采集程序发送过来的增量数据,并提供给服务端程序。消息传输通道本身不设置持久化功能,避免数据被泄露。服务端程序订阅消息传输通道中的消息队列,当消息传输通道中有新的数据时会将其推送到服务端程序的数据解析模块,数据解析模块按照约定的数据格式进行解析入库。
下面针对SQLite数据库文件监听、增量数据的获取、数据格式约定等介绍本解决方案。
本方案通过 Apache Commons IO 实现文件的监听,原理是通过另起一个线程按照固定频率扫描目录。通过FileAlterationMoniter启动监听线程、FileAlterationObserver选择需要监听的目录、重写FileAlterationListenerAdaptor的方法可以实现增量数据查询、发送的业务,下面是其中的部分代码:
File configFile = new File(filePath);
// 因为监听是以目录为单位进行的,所以这里直接获取文件的根目录
File dir = configFile.getParentFile();
本方案采用两种比较成熟的增量数据获取方法,即触发器与时间戳,实际使用中根据条件二选一即可。触发器方式适用于源表没有维护时间戳字段,程序无法直接获取到增量数据,且采集程序有权限为源数据库创建触发器。时间戳方式适用于应用程序本身维护了时间戳字段,应用本身对源表的新增、修改以及逻辑删除的同时会更新时间戳字段,采集程序通过比较时间戳字段的值即可获取增量数据。下面举例说明SQLite数据库触发器的创建。
新增操作的触发器:
为确保采集端与服务端对数据的一致理解,数据格式约定如下:
服务端根据此数据格式,确定数据同步的目的表、表中主键以及各个字段的名称和值等信息。
SQLite数据库基于其本身简单易用等特点已经在各个领域得到了广泛的应用,但目前绝大部分基于SQLite数据库的应用都是单机版,数据远程实时增量同步非常困难。本文通过引入采集程序、消息传输通道、服务端程序的集成解决方案,实现了基于文件探测的SQLite数据库远程实时增量同步。此方案通过采集程序、消息传输通道以及服务端程序这3层的划分,采集程序与服务端程序都只依赖于公网的消息传输通道,采集程序与服务端程序本身相互独立,通过约定的数据格式实现数据的打包与解析。本解决方案不限定服务端程序所用的数据库,可以是SQLite数据库、关系型数据库或者大数据类型的数据库。基于文件探测的方式是本解决方案实现数据实时同步的基础,此方法避免了通过传统的定时任务周期性查询数据库带来的资源开销,不过对于非采集目标的数据的改动也会触发后续的增量数据查询,造成程序无效执行。因此,本方案适用于同步源数据库中的热点数据。