tungsten API 同步日志清除Binlog失败的BUG解决
在简单修改tungsten API实现日志解析完成后,切换到下一个日志前,会进行此日志清除操作。此操作的目的是防止RelayLog同步mysql
在简单修改tungsten API实现日志解析完成后,切换到下一个日志前,会进行此日志清除操作。此操作的目的是防止RelayLog同步mysql master日志过多,引起磁盘空间占用过多的问题。此操作在BinlogPosition reset方法中增加了clearFile相关操作。
实现应用时发现一个问题:第一个解析的Binlog日志删除不了,以及中间偶尔会有一个binlog日志清除不了。(对于未清除的日志file会有记录,在下次清除file时会尝试再次删除,在操作过程中,如果我们的binlog日志足够多,重试多次后,第一个binlog有时是能删除成功的)
通过以上分析,猜测第一个Binlog 日志应该存在一种特殊逻辑,导致file在删除前,在内存中还保留着文件句柄,而且猜测会在JVM中遗留一段时间,当发生GC时,此句柄能被正常回收。
与是在调试MysqlExtractor解析源码中发现,,在processEvent方法中,当打开的InputStream流非空,且Binlog Position为0时,会openFile一个新的文件,对于此打开新的file逻辑本身是没有问题的,但是其处理代码是:
有可能InputStream 非空,
但是其在未关闭前就直接:fIS = new FileInputStream(file)//
对于此类问题在文件处理中是不可取的,如果原先文件未关闭,此文件句柄还会在JVM中占用空间,且导致此file不能被其它应用清除。(直到GC)
(而我们使用过程中第一个Binlog处理的position正是从0开始! 由于是API调用并未考虑对于从日志的中间开始解析,以及解析过程中保存此类状态)
以上BUG解决实际是对file流操作的问题,在以上操作前,加上流非空,关闭流的判断后,file能正常删除了。
最近两片小记都是对于mysql binlog处理过程中基于tungsten API同步过程中调试遇到的一些典型比较深刻的BUG,在此小记一下。
(最近项目是处理mysql binlog发现特定SQL的变化 ,为另一个系统做数据一致性而开发。算是一个小的尝试,现在开发已经接近尾声,实时性以及可行性都可取,下周开始将会把数据库实时修改考虑更新到redis缓存中去,(系统第一阶段是通过自己实现基于redis的分布式缓存),但是存在于一定局限性,且跟应用本身DAO耦合比较大。接下来会陆续记录开发过程中相关调研以及相关问题记录,有时间也会把第一队段,基于redis的分布式缓存架构简单记录于此,用于日后查看。)