Skip to main content

Command Palette

Search for a command to run...

使用 go-mysql-elasticsearch 把 MySQL 中的业务日志导入 Elasticsearch

Updated
2 min read

太长不看版:go-mysql-elasticsearch 能把 MySQL 数据库中的数据导入到 Elasticsearch 之中。

前言

相当一部分应用的日志是保存在数据库之中的,这些陈旧又稳定的应用在支撑着业务的运行。它们产生的日志通常来说也是有其价值的,但是如果能够融入到目前较为通用的 Elasticsearch 当中的话,可能有助于降低运维工作量,防止信息孤岛,并且进一步挖掘既有应用和业务的商业价值。

go-mysql-elasticsearch 就是这样一个项目,它可以从 MySQL 的数据表中读取指定数据表的数据,发送到 ElasticSearch 之中。它会使用 mysqldump 命令处理现有存量数据,并借助 binlog 的方式跟踪增量数据,从而保证 Elasticsearch 的数据和 MySQL 数据库中的数据保持同步。下面会简单讲一下这一项目的配置,并试验一个简单例子,最后根据实际情况进行一些改进。

条件和假设

  • 目前该工具支持 MySQL 和 ES 的版本都是 5.x。

  • MySQL 服务器需要开启 row 模式的 binlog。

  • 因为要使用 mysqldump 命令,因此该进程的所在的服务器需要部署这一工具。

  • 这一工具使用 GoLang 开发,需要 Go 1.9+ 的环境进行构建。

  • 可用的 MySQL、Elasticsearch 以及 Kibana 实例。

另外为了进行演示,这里做一点假设:

业务日志表

CREATE TABLE `biz_log` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `receive_content` text,
  `send_content` text,
  `fd_receive_content` text,
  `fd_send_content` text,
  `log_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8mb4;

四个 text 字段使用 JSON 格式存储了几个不同的日志种类。

工具构建

  1. go get github.com/siddontang/go-mysql-elasticsearch

  2. cd $GOPATH/src/github.com/siddontang/go-mysql-elasticsearch

  3. make

转换配置

执行 go-mysql-elasticsearch --help,会看到一系列的参数,最主要的参数就是 -config,这个参数用于设置转换过程所需的参数配置文件,在源码的 /etc/river.toml 中包含了一份配置样本。作者在这一配置样本中提供了非常详尽的注释,可以对转换过程做出很多定制。但是由于工具本身具备很好的适应能力,加上 ES 的强大功能,只需要一点简单的设置,就能够顺利完成常见任务了。

一个简单的配置:

# MySQL 的相关配置
# 指定用户必须具备复制权限
my_addr = "127.0.0.1:3306"
my_user = "root"
my_pass = "Flzx3000c"
my_charset = "utf8mb4"

# ES 相关配置
es_addr = "127.0.0.1:9200"
es_user = ""
es_pass = ""

# 数据源配置
# 以 Slave 模式工作
server_id = 10001
# mysql/mariadb
flavor = "mysql"

# mysqldump 路径,如果为空或者未设置,会跳过这一环节。
mysqldump = "mysqldump"
bulk_size = 128
flush_bulk_time = "200ms"
skip_no_pk_table = false


[[source]]
# 数据库名称
schema = "biz"
# 数据表同步范围,支持通配符
tables = ["biz_log"]

# 规则定义
[[rule]]
# 数据库名称
schema = "biz"
# 规则对应的数据表,支持通配符
table = "biz_log"
# 目标 ES 索引
index = "biz"
# 该规则在 ES 中生成的文档类型
type = "log_db"

同步

配置文件完成之后,就可以执行 ./go-mysql-elasticsearch -config=./river.toml,日志中会显示首先执行 mysqldump 导出存量数据,然后开始守护进程阶段,跟踪 binlog 并进行同步。

此时打开 Kibana,执行 GET _search,会看到数据库记录已经进入了 ES 中,并且按照我们定义的规则进行了索引。在守护进行运行期间,如果有新的数据插入,也会同步到 ES 之中。

但是这里我们会发现一个小问题,前面提到的 JSON 字段被作为单一的字符串存入了 ES 索引。这样就根据 JSON 中的特定字段进行搜索的需要就比较费劲了,而我们也知道,如果直接向 ES 提交文档,其中的 JSON 是会被映射为 Object 类型的。如果对 ES 索引进行数据类型的定义,会发现直接将 JSON 字段映射到 Object 类型后,同步过程会失败,返回错误认为将无效内容映射到了这一类型。因此可以推测是字符串并没有使用原有格式提交给 ES。

经过对代码的阅读跟踪,发现在 elastic/client.go 中对数据进行了一次 Json 编码:

    default:
        //for create and index
        data, err = json.Marshal(r.Data)
        if err != nil {
            return errors.Trace(err)
        }

下面就尝试进行一点改动,使之支持嵌套在字段内容中的 JSON 内容。

JSON

这里我想到了一个简单粗暴的办法就是,对数据报文进行一次检查,如果该字段内容是有效 JSON 的话,就使用 github.com/buger/jsonparserset 方法,将压缩后的 JSON 字符串重新赋值给编码后的 byte[]

首先给 BulkRequest 定义一个新方法,用于数据编码

func (b *BulkRequest) encodeData() []byte {
     jsonResults,_ := json.Marshal(b.Data)
     // 判断是否有效的 JSON 数据
     isJson := func(s string) bool {
         var js map[string]interface{}
         return json.Unmarshal([]byte(s), &js) == nil

     }
     for key, value := range b.Data {
         stringValue, ok := value.(string)
         // 如果字段内容是字符串并且是 JSON 格式
         if ok && isJson(stringValue) {
             // 设置编码后内容该字段的值为原文
             jsonResults,_ = jsonparser.Set(jsonResults, []byte(stringValue), key)
            }
     }
     return jsonResults
 }

然后将原有的 data, err = json.Marshal(r.Data) 替换为 data = r.encodeData(),再次构建运行。会看到 ES 成功的将 JSON 字段进行了解析,生成了 Object 类型的映射关系。

补充说明

这里引用go-mysql-elasticsearch功能及性能验证 一文的性能测试结果:

1.全量同步
支持:需要安装mysqldump(mysql自带),同步11.5w数据,耗时3分13秒。
全量基于mysqldump,需要将工具和mysql安装在同一个节点,其它方式尚未找到。
2.增量同步
支持。
增量插入20W数据,耗时8分钟。
删除20w条数据,耗时6分。
更新20w条数据,12分钟。

这一工具还有一些其它亮点,例如多表聚合、字段过滤、自定义字段映射等。

相关链接

  1. 项目地址:https://github.com/siddontang/go-mysql-elasticsearch

  2. 配置文件样本:https://github.com/siddontang/go-mysql-elasticsearch/blob/master/etc/river.toml

  3. Fork 地址:https://github.com/fleeto/go-mysql-elasticsearch

  4. 作者原版教程:https://www.jianshu.com/p/96c7858b580f

  5. go-mysql-elasticsearch 功能及性能验证 :https://my.oschina.net/u/2282993/blog/1821930

  6. JsonParser:https://github.com/buger/jsonparser

More from this blog

龙虾恐慌:AIOps 又要改名了?

ChatGPT 开始,把 AI 拉近到普罗大众的面前,让无数人感受到 AI 的亲民魅力。而龙虾,则把大模型驱动的自动化能力,突然间变得水灵灵、活泼泼地走进千家万户。它不只是“风口上的猪”,而是风口本身。热度高到让 Mac mini 一度断货,不知道这在不在库克的预料之内。 每代人都有每代人的鸡蛋,春节期间,我就领了我的鸡蛋。翻出古老的 MacBook Air M1,充值各种大模型。当然了,这个工具

Mar 9, 20261 min read

再见 2025

我猜不少人以为这个号废了吧?并没有,只是今年变化有点大,一直有种抄起键盘,无从说起的感觉,所以一直偷懒到今天,2025 的最后一天。 今年是我的第四个本命年,去年末一期播客里,大内说本命年不是灾年,是变化年,有危也有机。可是讲真啊,只看到危,没看到机。 各种因缘际会,从鹅厂跳槽到前东家,已经接近四年,第一个合同期已经进入尾声。除了前两年还在云原生领域嗷嗷叫,后两年基本都是些鸡零狗碎的东西了,用老东家的术语说是——偏离主航道,可谓是前景暗淡了。 一旦确定要滚蛋,反倒心思轻松起来,每天骑着我的小红车...

Jan 5, 20261 min read

辅助编程?dora 说:我知道你很急可是请你别急

从 OpenGPT 把大模型的火烧旺了之后,这三年来,相信很多组织或摩拳擦掌、或躬身入局,希望借助聪明能干的大模型,或想偿还技术宅,或想降本增效,或想弯道超车。一时间,沉寂许久的 AIxx 又活过来了,LLM Ops、Vibe Coding、中医大模型、GPT 算命等等,全都老树发新芽,焕发了勃勃生机。那么视角拉回从业者最关注的饭碗相关的领域之一——AI 辅助开发,产生了什么触动,应该如何拥抱呢? DORA 的年度报告中给出了很有意思的结论——强者恒强。 执行摘要部分总结了几个有趣的点: 问题...

Oct 6, 20251 min read

[译]dora:ai 辅助软件开发状态报告

执行摘要 在 2025 年,科技领导者面临的核心问题已不再是“是否要采用 AI”,而是“如何实现其价值”。 DORA 的研究基于超过 100 小时的定性访谈和来自全球近 5,000 名技术专业人士的问卷调查。研究揭示了一个关键事实:AI 在软件开发中的主要角色是“放大器”。它会放大高效能组织的优势,也会凸显组织的缺陷。 关键结论:AI 是放大器 AI 投资的最大回报并非来自工具本身,而是来自组织底层系统的战略性建设: 高质量的内部平台 清晰的工作流 团队的协同能力 缺少这些基础,AI ...

Oct 2, 202514 min read

僭越了,有人在用 Rust 写 Kubernetes

一个新语言问世,最爱做的事情之一,就是重写存量软件了。 云原生喝酒 SIG 重点扶持项目——rk8s(https://github.com/rk8s-dev/rk8s) 也可以归在这个范畴里,只不过这个项目重写的东西比较大,是 Kubernetes。 从 2025 年 1 月第一个 Commit 开始,到现在有了 200 多次 Commit,十几万行代码。当然距离 Kubernetes 的几百万行代码还差得远——老马就是喜欢整这种大无畏项目。 另外该项目也是国内第一个脱离 Cargo 转向使用 ...

Sep 27, 20253 min read

【伪】架构师

342 posts