一种日志保存方法及装置
技术领域
本发明涉及日志保存技术,尤其涉及一种日志保存方法及装置。
背景技术
日志保存是一种用于记录用户在网络中的行为的技术,采用日志保存技术后可以方便的对用户在网络中的行为进行查询、跟踪和分析。日志保存技术在即时通信系统、银行系统、电话系统以及网站系统等网络系统中都得到了广泛的应用,例如,在电话系统中,日志系统会记录每次通话的双方号码、起始时间、产生的话费等内容;在银行系统中,日志系统会记录用户的存取款记录;在网站系统中,日志系统会记录网站的访问记录;在即时通信系统中,日志系统会记录即使通信软件的登录记录等。
图1所示为日志系统的结构示意图,由图中可见,日志系统主要包括日志产生装置和日志保存装置,其中日志产生装置用于产生日志,可以是处理业务的终端(如ATM机),也可以是处理业务的后台服务器(如电话交换机、计费服务器等);日志保存装置用于接收日志产生装置产生的日志并对其进行保存,日志可以保存在文件中,也可以保存在数据库中,其中后者因为其易管理性而成为主流。
现有技术的日志系统中,日志保存装置可以设置在日志产生装置中,也可以独立于日志产生装置作为一个单独的功能实体,下面分别予以说明:
将日志保存装置设置在日志产生装置中即是将日志产生装置产生的日志直接保存在本地磁盘中,例如,常见的门户网站系统由一个或多个网站服务器组成,这些网站服务器就是日志产生装置。当有一个用户访问网站时,网站服务器把用户的访问日志记录(如时间、IP等)直接保存在本地磁盘,以后再定时汇总这些日志信息。这种将日志保存装置设置在日志产生装置中的日志保存方式的实现简单,不用在日志产生装置和日志保存装置之间设计专门的日志发送/接收网络协议,但是其缺点也很明显,由于日志产生装置的主要使命是响应和处理用户的业务请求,频繁的日志保存操作(通常是很慢的磁盘操作)会大大影响日志产生装置的业务处理能力。因此,这种将日志保存装置设置在日志产生装置中的日志保存方式只适合日志量较小,或者只需抽样记录部分日志的应用环境。
图2所示为独立设置日志保存装置的日志系统的结构示意图,由图中可见,日志产生装置和日志保存装置为各自独立的功能实体,日志产生装置和日志保存装置之间通过特定的网络端口连接,一个日志保存装置与多个日志产生装置相对应,可保存多个日志产生装置产生的日志。日志产生装置和日志保存装置之间需要预先设定日志发送/接收网络协议,日志产生装置负责把日志发送到日志保存装置特定的网络端口,日志保存装置负责监听特定的网络端口,一旦有日志到达,就把日志接收下来并将其保存到磁盘。
日志保存装置中的日志接收模块将日志保存到磁盘的方式主用有三种,第一种方式是将日志直接插入到数据库,由于多了一层数据库操作,所以保存速度比较缓慢;第二种方式是将日志直接保存到文件,这种方式的保存速度比第一种方式要快,但是文件形式的日志不方便汇总和查询;第三种方式是先将日志保存到文件,再读取文件内容,把日志一次一行地或一次多行地插入到数据库中,一次多行的操作方法能够大大提高数据库插入速度。无论采取上述三种保存方式中的哪一种,都面临一个重要的问题,由于磁盘I/O(Input/Output,输入/输出)的速度赶不上网络I/O的速度,因此在日志量很大的情况下,会导致日志来不及写入磁盘而丢失。
现有技术中通常采用日志保存装置集群的方式来解决磁盘I/O赶不上网络I/O而丢失日志的问题,图3所示为采用集群式日志保存装置的日志系统的结构示意图,由图中可见,多个日志保存装置组成一个集群,集群中的每个日志保存装置与一组日志产生装置相对应,不同组的日志产生装置把日志发到对应的日志保存装置,从而减轻了单个日志保存装置的负担。这种方式的优点是可以平行扩展,只要增加足够数量的日志保存装置,就可以解决日志丢失的问题。但在增加日志保存装置的同时日志系统的成本也会大大提高,并且由于日志分散保存在不同的日志保存装置中,不方便进行日志的汇总和查询。
发明内容
本发明提供一种日志保存方法及装置,用以解决现有技术在进行日志保存过程中日志容易丢失、日志入库耗时过长的问题。
本发明方法包括:
一种日志保存方法,所述日志由日志产生装置产生,包括步骤:
接收并缓存日志产生装置产生的日志;
读取缓存中的日志,将其保存在二进制形式的日志文件中;
将所述二进制形式的日志文件转换为文本形式的日志文件,将该文本形式的日志文件导入数据库中进行保存。
每间隔预定时间读取一次缓存,将缓存中保存的日志全部读出。
当缓存中保存的日志所占用的存储空间达到预定数值时读取一次缓存,将缓存中保存的日志全部读出。
每个二进制形式的日志文件中保存了设定时长内从缓存中读出的全部日志。
每个二进制形式的日志文件中保存了设定数量的从缓存中读出的日志。
调用数据库底层接口将文本形式的日志文件批量导入数据库中。
一种日志保存装置,用于保存日志产生装置产生的日志,包括:
日志接收模块,用于接收日志产生装置产生的日志,将其保存在缓存中;
日志导出模块,用于读取缓存中的日志,将其保存在二进制形式的日志文件中;
数据转换模块,用于将二进制形式的日志文件转换为文本形式的日志文件;
数据库导入模块,用于将文本形式的日志文件导入数据库中进行保存。
所述缓存设置在日志接收模块中,或者为所述装置中的单独设置的模块。
所述日志接收模块实时接收日志产生装置产生的日志。
所述日志导出模块每间隔预定时间读取一次缓存,将缓存中保存的日志全部读出。
所述日志导出模块在缓存中保存的日志占用的存储空间达到预定数值时读取一次缓存,将缓存中保存的日志全部读出。
所述数据库导入模块调用数据库底层接口将文本形式的日志文件批量导入数据库中。
本发明有益效果如下:
本发明采用缓存技术对接收到的日志产生装置产生的日志进行缓存,采用批量写的方式一次性地把从缓存中读出的日志全部写到磁盘上的二进制形式的日志文件中,将二进制形式的日志文件转换为文本形式的日志文件后,利用数据库的批量导入工具将该文本形式的日志文件批量导入数据库中进行保存。由于缓存的存取速度远远大于网络速度,因此可以保证不会丢失日志产生装置产生的日志,采用批量写的方式一次性地把从缓存中读出的日志全部写到磁盘上的二进制形式的日志文件中,可以保证磁盘写入的最大速度,避免了由于磁盘速度导致的日志丢失问题;利用数据库的批量导入工具将文本形式的日志文件批量导入数据库中进行保存可以缩短日志入库的时间,本发明完全解决了日志入库时间过长的问题,且硬件资源消耗很少。
附图说明
图1为日志系统的结构示意图;
图2为独立设置日志保存装置的日志系统的结构示意图;
图3为采用集群式日志保存装置的日志系统的结构示意图;
图4为本发明的日志保存装置的结构示意图;
图5为本发明的日志保存的流程图。
具体实施方式
本发明针对现有技术的缺陷,提出一种适用于日志量很大的情况下的日志保存方法及装置,下面将结合各个附图对本发明的主要实现原理及其具体实施方式进行详细的阐述。
图4所示为本发明的日志保存装置的结构示意图,由图中可见,本发明的日志保存装置的结构主要包括:
日志接收模块,接收日志产生装置产生的日志,将其保存在缓存中;
日志导出模块,读取缓存中的日志,将其保存在磁盘上的二进制形式的日志文件中;
数据转换模块,将磁盘上的二进制形式的日志文件转换并保存为文本形式的日志文件;
数据库导入模块,将文本形式的日志文件导入磁盘的数据库中进行保存。
上述缓存即可以设置在日志接收模块中,也可以单独设置,作为日志保存装置中的独立模块。
图5所示为本发明的日志保存的流程图,参见图5并结合图4,本发明的日志保存的主要实现过程如下:
步骤S10、日志接收模块实时监听日志产生装置和日志保存装置之间的特定网络端口,接收日志产生装置发送过来的日志。
步骤S11、日志接收模块将接收到的日志保存到一块缓存区里,由于内存的存取速度远远大于网络速度,因此可以保证不会丢失日志;
缓存区用“共享内存”技术实现,缓存区在数据结构上是一个环,假设缓存区的大小是K字节,缓存区当前的头部是第H字节,尾部是第T字节,日志接收模块总是把接收到的日志写到缓存区的尾部,即从第(T+1)%K个字节开始写,其中,%表示对括号里面的数值进行取余操作。也就是说,如果T+1=K,那么从缓存区的第0个字节开始写,这样就实现了环状缓存区;
一般来讲,日志的格式都是比较固定的,在设计时通常设计成定长的二进制数据(每一条日志占用相同大小的存储空间),因此,缓存区的内容是二进制数据,这主要是由于二进制数据比表示相同内容的文本数据节省存储空间,可以减少对缓存区大小的要求。比如,电话号码88888888,如果用文本数据表示,需要8个字节,而用二进制数据表示时,其数据形式为00000101010011000101011000111000,只需要4个字节。
步骤S12、日志导出模块从缓存区的头部开始读取日志,将其写入磁盘内的二进制形式的日志文件中;
日志导出模块每间隔预定时间或者在缓存中保存的日志占用的存储空间达到预定数值时读取一次缓存区,将缓存区中保存的日志全部读出,日志导出模块采用了批量写的方式一次性地把从缓存区中读出的日志全部写到磁盘上的二进制形式的日志文件中,批量写技术可以保证磁盘写入的最大速度,避免了由于磁盘速度导致的日志丢失问题。
二进制形式的日志文件的保存方式主要有两种,一种方式是每个二进制形式的日志文件中保存设定时长(如24小时)内从缓存中读出的全部日志,即设定时长内从缓存中读出的全部日志形成一个二进制形式的日志文件;另一种方式是每个二进制形式的日志文件中保存设定数量(如1000万条)的从缓存中读出的日志,即每当从缓存中读出的日志达到设定数量即形成一个二进制形式的日志文件。
假设缓存区的大小是K字节,当前的头部是第H字节,尾部是第T字节,那么需要导出的内容是:
1)如果H<=T,需要导出的内容是[H,T];
2)如果H>T,那么需要导出的内容是[H,K-1]和[0,T]。
日志导出模块用标准C函数库的fwrite()函数可以方便地实现批量写,例如,fwrite(pszBuffer,iLogLen,iLogCount,pfOutputFile),表示把缓存区pszBuffe的内容写到文件pfOutputFile中,写iLogCount条日志,每条日志iLogLen个字节。
步骤S13、数据转换模块将磁盘上的二进制形式的日志文件转换并保存为文本形式的日志文件;
日志保存在二进制文件中,不方便做各种查询、追踪和分析,我们需要把它们放到数据库中,以方便查询,大部分数据库产品(如Oracle、DB2、SQLServer、MySQL等)都提供了批量导入的工具,但这些数据库产品只能批量导入文本文件,因此,需要数据转换模块将二进制形式的日志文件转换并保存为符合数据库导入格式要求的文本形式的日志文件。
例如,对于论坛登录日志:用户ID(整数)、登录时间(整数)、登录IP(整数)
其二进制形式的日志内容为:
00000101 01001100 01010110 00111000
01000011 00001100 10001110 01101011
11001010 10000100 00100010 00100111
其转换后的文本形式的日志内容为:
88888888,2005-08-2423:12:43,202.132.34.39
步骤S14、数据库导入模块将文本形式的日志文件导入磁盘的数据库中进行保存;
本发明主要用于日志量很大的应用环境中,如每天10亿条,如果用数据库的Insert语句插入大量的日志数据,入库时间会非常长,约需要10个小时左右。即时使用“一次插入多行”的插入方式,也需要5个小时左右。插入慢的原因是数据库需要频繁对待插入的表进行加锁/解锁操作,需要频繁地做表文件空间的查找/分配操作。
大部分数据库产品(如Oracle,DB2,SQL Server,MySQL)都提供了批量导入的工具,如MySQL的Load Data In file语句,SQL Server的Bulk Insert语句等;
例如,MySQL的批量导入的语句为:Load Data infile‘/tmp/source.txt’intotable TargetTableName fields terminated by‘,’;
SQL Server的批量导入的语句为:Bulk insert TargetTableName from″/tmp/source.txt″with(FIELDTERMINATOR=′,′);
在本发明中,数据库导入模块调用数据库提供的接口或者SQL语句,如上述Load Data Infile语句或者Bulk Insert...From语句,使用批量导入方式将文本形式的日志文件导入数据库中,由于这种方式直接调用数据库底层接口对数据库进行写操作,因此这种方式的导入速度比Insert语句快10~1000倍,使10亿条日志仅用约30分钟就可以全部入库。
本发明采用缓存技术、批量写技术以及批量导入数据库技术进行日志的保存,解决了日志入库时间过长的问题,完全避免了因为磁盘速度小于网络速度造成的日志丢失,且硬件资源消耗很少。
显然,本领域的技术人员可以对本发明进行各种改动和变型而不脱离本发明的精神和范围。这样,倘若本发明的这些修改和变型属于本发明权利要求及其等同技术的范围之内,则本发明也意图包含这些改动和变型在内。