Python实战案例:elasticsearch与数据库mysql的同步(上)
在一些企业的面试中,常常遇到elasticsearch全文检索方面的问题,这也是企业最常遇到的问题。由于Elasticsearch就是专门用于搜索的,所以我们会将新增的数据放入Elasticsearch中用于搜索,也就有了这样的常见的场景,需要将Mysql中的数据同步到Elasticsearch中。
从方法上来讲,Mysql数据同步到ES中可分为两种,分别是全量同步和增量同步。全量同步表示第一次建立好ES索引之后,将Mysql中所有数据一次性导入到ES中。增量同步表示Mysql中产生新的数据,这些新的数据包括三种情况,就是新插入Mysql中的数据,更新老的数据,删除的数据,这些数据的变动与新增都要同步到ES中。
一、mysql与elaticsearch同步的方案介绍
对于mysql与elasticsearch同步的方案有以下几种。
1、基于Mysql的binlog日志订阅:binlog日志是Mysql用来记录数据实时的变化。如下图所示。
这种方案以binlog同步数据库的变化,当有数据发生变化时,可以变化的数据消息放在队列中,然后从队列中分别取出信息进行处理,这种方式就有了生产者消费者模式的思想,这样,接收binlog变化日志的任务就由kafka消息队列负责,当有新的日志信息消费后,再对elasticseach中的数据进行更新。基于Mysql的binlog日志订阅就是这样完成mysql与elasticsearch同步数据变化的。
对于这样的方式主要binlog同步组件。目前实现的有国内的阿里巴巴开发的canal。
2.使用go-mysql-elasticsearch。
go-mysql-elasticsearch是一款使用go语言开发的同步数据到ES的工具。
3、ES官方数据收集和同步组件logstash
对于以上三种方法来说,我们以python语言实现为主,因此主要介绍第一种基于Mysql的binlog日志订阅方法。
二、mysql中binlog日志的开启
这里以windows系统为例,在windows中安装mysql后,mysql的配置文件my.ini被放置在“C:\ProgramData\MySQL\MySQL Server 5.6”中。打开my.ini文件后,需要将文件中“#log-bin”前面的“#”号去掉。如下图所示。
去掉前面的#号后,在windows的服务中重新进行开启mysql服务。
当mysql的服务重启后,可以进入到mysql数据库的控制台,通过如下命令可以显示当前bin-log的值。
show global variables like “%log_bin%”
在mysql控制台执行上述命令后运行结果如下图所示。
除了设置logbin外,还需要设置logformat这个mysql环境下的系统变量值,设置前可以先显示binlog_format变量的值,显示该变量值的命令如下。
show global variables like “%log_format%”
运行上述命令后的结果如下图所示。
从图中可以得知,binlogformat的原来的值默认为STATEMENT,通过set global命令可以设置binlogformat的值,具体set global命令的完整格式如下。
set global binlog_format=”ROW”
这里将binlog_format变量的值设置成“ROW”,即行模式。
再次调用show global variables like “%logformat%”命令后可以显示出binlogformat变量修改之后的值。
在mysql数据库中,完成了“logbin”和“binlogformat”这两个系统变量的设置后,对数据库的每次操作就会产生binlog日志文件,python需要的就是保持读取该文件的状态,只要binlog日志文件发生变化,就可以读取出相关的信息。
三、python使用mysql-replication模块实现对binlog日志的实时监控
binlog日志文件配置成功后,python是可以使用mysql-replication模块对binlog日志进行实时监控的。Mysql-replication的安装方法如下:
pip3 install mysql-repliation
mysql-replication中有一个BinLogStreamReader类,该类对binlog日志进行流式的实时读取,参数中connetionsettings完成对数据库参数的配置,serverid是为服务器起一个id,我们实验的服务器只有一台,这个id可任意。only_schema参数起到了监控数据库中指定的数据库名称,onlyevents参数限定对指定数据库中的任意表进行增删改的操作,一般同步数据库肯定是对数据库中的记录进行了增删改,所以一般onlyevents常用的就是增删改的events操作,删除对应的events是DeleteRowsEvent,更新对应的events就是UpdateRowsEvent,增加对应的events就是WriteRowsEvent。
当python把BinLogStreamReader类实例化后,传入相应的参数,数据库日志中的内容就会被返回到一个变量中,把这个变量进行遍历,对其中遍历到的每一行进行数据的提取,每行中的values键存储的就是日志增加的数据信息。对应的代码如下。
from pymysqlreplication import BinLogStreamReader
from pymysqlreplication.row_event import (
DeleteRowsEvent,
UpdateRowsEvent,
WriteRowsEvent,
)
import json
import sys
MYSQL_SETTINGS={
"host":"localhost",
"user":"root",
"password":"admin"
}
stream=BinLogStreamReader(connection_settings=MYSQL_SETTINGS,server_id=4,blocking=True,only_schemas=["booksme"],only_events=[DeleteRowsEvent,WriteRowsEvent,UpdateRowsEvent])
for binlogevent in stream:
for row in binlogevent.rows:
event={"schema":binlogevent.schema,"table":binlogevent.table}
if isinstance(binlogevent,DeleteRowsEvent):
event["action"]="delete"
event["data"]=row["values"]
elif isinstance(binlogevent,WriteRowsEvent):
event["action"]="insert"
event["data"]=row["values"]
elif isinstance(binlogevent,UpdateRowsEvent):
event["action"]="update"
event["data"]=row["values"]
print(json.dumps(event,ensure_ascii=False))
sys.stdout.flush()
代码中的数据库使用的是booksme,其中有一张book表,其中包含了一些书的名字和价格。如下图所示。
现在运行读取binlog日志文件的python程序,对这个数据库中的book表插入一条数据,看一下binlog日志文件的python程序控制台最终的输出结果,如下图所示。
由图中可以看出,对数据库中删除了一本“聊斋”的书,然后又添加了一本“聊斋”的,添加的书定价为110.10,这样的信息在数据库添加的同时,在pycharm程序的控制台也做了删除和添加内容的输出。
这就通过python的mysql-replication模块实现了程序同步到了数据库的变化。
四、kafka环境的搭建
前面python程序已经获取到了binlog的日志信息,现在需要指派一个生产者去把这个信息订阅发布出去,然后由消费者对得到的信息进行消费,消费的结果就是同步到elasticsearch中,这里生产者消费者模式的队列常常采用kafka,对于kafka的安装步骤做一下说明。
如果要实现kafka服务器,必须有zookeeper服务器的支持。zookeeper可以到官网上去下载zookeeper程序。如下图所示。
在这里面可以点击“Download”即可下载zookeeper,下载后直接解压到一个指定的文件夹中,如被解压到D盘根目录下的zookeeper目录下,也就是D:\zookeeper。在此zookeeper目录下找到“zoosample.cfg”文件,将其重命名为“zoo.cfg”,打开“zoo.cfg”找到并编辑dataDir=D:\zookeeper\tmp,这里放置数据的地方。接下来需要添加系统变量:ZOOKEEPERHOME=D:\zookeeper。如下图所示。
接下来,编辑path系统变量,添加路径:%ZOOKEEPER_HOME%\bin。如下图所示。
打开新的cmd,输入“zkServer“,运行Zookeeper。如下图所示。
zookeeper安装成功后,从kafka官方网站中下载kafka,如下图所示。
解压并进入Kafka目录,这里解压到D的kafka目录下。
进入kafka的config目录找到文件server.properties并打开,在文件中找到并编辑log.dirs=D:\kafka\kafka-logs。
kafka目录中bin目录下有windows目录,kafka-server-start.bat就是kafka服务的启动文件。指定kafka配置文件server.prperties的路径即可启动kafka服务。命令如下。
kafka-server-start.bat ..\..\config\server.properties
命令启动后的结果图片如下图所示。
如果在启动中提示media.properties的错误,可以将bin中windows目录下config配置目录中的文件全部删除,或者修改media.properties中的设备号,如下图文件结构的显示。
在bin的windows目录中分别有文件kafka-console-producer负责生产者的启动,文件kafka-console-consumer负责消费者的启动,用生产者的启动文件启动服务器,并启动topic,topic也是消息机制中生产者和消费者中订阅/发布的关键,利用topic可以实现生产者消费者模式的重复消费。
使用kafka-console-producer在topic中发送消息的命令如下。
kafka-console-producer.bat --broker-list localhost:9092 --topic test
这里的--broker-list就是生产者和消费者联系的中间者broker。broker就是缓存代理,Kafka集群中的一台或多台服务器统称broker。
运行命令后的结果如下图所示。
再次启动一个cmd窗口,执行kafka-console-consumer消费者指令,指令如下。
kafka-console-consumer --bootstrap-server localhost:9092 --topic test
运行该指令后的结果如图所示。
现在可以在producer生产者的cmd窗口中“>”号后面输入任意一句话,如下图所示。
在consumer消费者的cmd窗口中对应输出如下图的结果。
由图可以看出,生产者有一个消息的发布,消费者就有一个消息的显示。
代码对应的github地址:https://github.com/wawacode/mysqlelasticsearchsynchronism
教程对应的视频地址:
mysql与elasticsearch同步1-数据库binlog的设置及python读取