logstash同步mysql数据到Elasticsearch遇到问题记录

问题

1.java.lang.OutOfMemoryError: Java heap space

从报错信息看是堆溢出,为什么会堆溢出呢?logstash是读取mysql的数据,经过filter处理以后再发送到ES;那么这个读取mysql的过程其实就和我们写代码,将大量数据读取到内存里,导致内存溢出是一样的;

解决办法和平时写代码的注意点是一样的,将数据分批读。

理解了这个,就想怎么分批读,解决就在input输入插件

input {
   jdbc {
       jdbc_driver_library => "这里我省略了,其他教程有"
       jdbc_dirver_class => "com.mysql.cj.jdbc.Driver" 
       jdbc_connection_string => "这里我省略了,其他教程有"
       jdbc_user => "root"
       jdbc_password => "root"
       jdbc_default_timezone => "Asia/Shanghai"

       #重点在这里 开启分页
       jdbc_paging_enabled => true
       jdbc_page_size = 10000 
       
       schedule => "* * * * *"
       statement_filepath => "写你放sql文件的地址"
       tracking_column => "update_time"
       tracking_column_type => "timestamp"
       .....下面的配置省略吧,敲起来好累,重点也不在这里,建议看官方文档
  } 
}

配置 jdbc_paging_enbbled => true、jdbc_page_size = 10000;

将这两个配置即可,其实我在看input_jdbc插件文档的时候,就好奇,这两个分页的参数,不配会有什么问题吗?配了又会怎么样?最终我没配置,但是心里有疑问。然后在一开始需要初始化大量数据的时候就报错了,立马就想到这里应该配置,配置以后就没有堆溢出的问题了;

小问题:jdbc_page_size设置为多少合适?

我的做法:先设置10000条,然后运行起来,观察服务器内存消耗情况;

                  1.设置10000

                  2.free -h 观察服务器内存使用情况

total used
7.7G2.5G

 

 

 

                  3.启动logstash,然后继续free -h观察内存使用情况

    

total used
7.7G3.5G

 

 

 

观察出我的10000条数据量大概会占用1G的内存,那么如果配置的-Xms6g、-Xmx6g,我应该可以配置的条数最多有6G/1G * 10000 = 6万条,冗余一点,大概可以配置为40000;

 

网上还有其他几种解决办法

1.修改jvm.options

jvm设置

我理解的是,jvm.options是需要设置的,但是并不一定能解决这个报错,这个设置在上线以前就应该设置好,比如我设置成了-Xms5g、-Xmx5g,还是会出现这个报错;

如果你的数据量恰好没那么大,这么设置也能解决问题;像我初始化的数据比较大,设置了以后还是报错,所以还是应该在读取数据的时候就设置分批;

另外jvm.options官方文档建议设置成 大于4g,小于8g,这个我暂时不是很理解这个建议。还没有时间详细看,先存疑在这里。

官方文档设置搬运:

  • The recommended heap size for typical ingestion scenarios should be no less than 4GB and no more than 8GB.
  • 对于典型的(数据)输入场景,推荐的堆大小应该不小于4GB,不超过8GB。
  • CPU utilization can increase unnecessarily if the heap size is too low, resulting in the JVM constantly garbage collecting. You can check for this issue by doubling the heap size to see if performance improves.
  • 如果堆大小太低,CPU利用率可能会不必要地增加,导致JVM不断地收集垃圾。您可以通过加倍堆大小来检查此问题,以查看性能是否有所提高。
  • Do not increase the heap size past the amount of physical memory. Some memory must be left to run the OS and other processes. As a general guideline for most installations, don’t exceed 50-75% of physical memory. The more memory you have, the higher percentage you can use.
  • 不要增加堆大小超过物理内存量。必须留出一些内存来运行操作系统和其他进程。作为大多数安装的一般指南,不要超过物理内存的50-75%.内存越多,可以使用的百分比就越高。
  • Set the minimum (Xms) and maximum (Xmx) heap allocation size to the same value to prevent the heap from resizing at runtime, which is a very costly process.
  • 将最小(XMS)和最大(XMX)堆分配大小设置为相同的值,以防止堆在运行时调整大小,这是一个非常昂贵的过程。
  • You can make more accurate measurements of the JVM heap by using either the jmapcommand line utility distributed with Java or by using VisualVM. For more info, see Profiling the Heap.
  • 您可以使用与Java一起分发的jmap命令行实用工具或使用VisualVM对JVM堆进行更精确的测量。有关更多信息,请参见Profiling the Heap.

2.另外一种解决办法是通过修改sql分批,这个我还没有细看,先留链接,有空研究区别

    修改sql

问题2.logstash将mysql中的数据导入elasticsearch时,发现数据库中的tinyint(1)这种类型的就会被转成boolean

     这个问题同样会在我们写java代码的时候出现,解决办法一致就行:

     jdbc_connection_string => "jdbc:mysql://localhost:3306/my_db?tinyInt1isBit=false"

     这么设置就可以解决问题,注意区分大小写

     也有其他解决办法,将数据库设置tinyint(1) 设置为tinyint(2),个人觉得上一种好一些,一般是不知道上一种处理,才使用下一种,我是这么理解的;

      但是我在加了tinyInt1isBit=false这个设置以后,再启动logstash发现仍然将之前那个字段处理成了boolean,为什么呢,并且重启了几次都这样,难道是我的设置没生效?

      坐着想了一会,我的logstash设置启用了持久化,也就是logstash.yml配置文件中的 queue.type: persisted(默认是memory)这里开启了持久化,持久化开启了就是容灾的,防止logstash突然挂掉,然后读取的数据没处理,所以数据会持久化到磁盘上,下次再启动就会读取磁盘上持久化的数据;那么我刚刚修改的配置没生效会不会是因为,我再启动logstash,logstash优先处理上次结束以后还保存在queue里面的数据。于是我去data/queue/{你的pipeline.id} 就是配置持久化queue存储的地方,把下面的数据删掉,再重启,修改看起来就生效了,验证猜想成功。

 

 

 

   

 

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值