纯手工打造每一篇开源资讯与技术干货,数十万程序员和Linuxer已经关注。
由于业务的发展,一些实时统计的需求越来越多。怎么办呢?
但是对于有入库还有自己记录到日志的这显然是多此一举。因为MySQL本身就有帮你记录日志, 而且记录的日志比自己应用程序的要准确的多(MySQL 需要开启row模式)。
解析MySQL Binlog,并获取我们想要的Event。
过滤出我们关心的表。
将获得的相关数据实时的保存到相关存储中(一般使用redis存数据,之后再定时刷入MySQL)。
模拟步骤:
我们这边模拟实时算订销售总额,和订单量。
使用python-mysql-replication作为实时解析MySQL Binlog的日志利器(推荐使用 阿里的 canal,这里主要看公司的开发人员擅长什么而决定)。
我们只关心 WriteRowsEvent (事件号 30)。
我们只关心 ord_order 表产生的 WriteRowsEvent 事件。
在原来统计的基础上加上本次订单的信息并保存到Redis(使用打印来代替保存到Redis)。
--创建演示的ord_order表 CREATETABLEord_order( order_idINTNOTNULLAUTO_INCREMENTCOMMENT'订单ID', amountINTNOTNULLDEFAULT0COMMENT'订单金额(分)', create_timeDATETIMENOTNULLDEFAULTCURRENT_TIMESTAMPCOMMENT'创建时间', PRIMARYKEY(order_id) )COMMENT='订单表';
--查看当前日志所在位置 SHOWMASTERSTATUS; ------------------ ---------- -------------- ------------------ ------------------- |File|Position|Binlog_Do_DB|Binlog_Ignore_DB|Executed_Gtid_Set| ------------------ ---------- -------------- ------------------ ------------------- |mysql-bin.000012|469|||| ------------------ ---------- -------------- ------------------ -------------------
--插入几笔订单 INSERTINTOord_order(amount)VALUES (1000), (2000), (3000);
--查看当前日志所在位置 SHOWMASTERSTATUS; ------------------ ---------- -------------- ------------------ ------------------- |File|Position|Binlog_Do_DB|Binlog_Ignore_DB|Executed_Gtid_Set| ------------------ ---------- -------------- ------------------ ------------------- |mysql-bin.000012|712|||| ------------------ ---------- -------------- ------------------ -------------------
#!/usr/bin/envpython #-*-coding:utf-8-*-
frompymysqlreplicationimportBinLogStreamReader
#链接数据库的参数因为pymysqlreplication底层使用的是python-mysql mysql_settings={ 'host':'192.168.1.233', 'port':3306, 'user':'HH', 'passwd':'oracle' }
#这pymysqlreplication的server_id和从Binlog的什么位置开始解析 stream=BinLogStreamReader(connection_settings=mysql_settings, server_id=100, blocking=True, log_file='mysql-bin.000012', log_pos=469)
#初始化订单统计数据 order_count_total=0 order_amount_total=0
#不停的解析获取解析的Binlog forbinlogeventinstream:
#碰到WriteRowsEvent并且表是ord_order则进行统计 ifbinlogevent.event_type==30andbinlogevent.table=='ord_order': binlogevent.dump()#打印事件相关信息
#同时计算出订单数和金额数组,如:[(1,9),(1,4)] stat=[(1,row['values']['amount'])forrowinbinlogevent.rows]
#分别获得订单数数组如:[1,1]。销售额,如:[9,4] order_count,order_amount=zip(*stat) order_count_total =sum(order_count) order_amount_total =sum(order_amount)
#打印本次事件产生的订单数和销售额 print'order_count:',order_count print'order_amount:',order_amount
#打印总的订单数和销售额 print'order_count_total:',order_count_total print'order_amount_total:',order_amount_total
运行代码
[root@centos7tmp]#pythontest.py ===WriteRowsEvent=== Date:2016-11-16T17:11:11 Logposition:681 Eventsize:54 Readbytes:12 Table:test.ord_order Affectedcolumns:3 Changedrows:3 Values: -- ('*',u'order_id',':',1) ('*',u'amount',':',1000) ('*',u'create_time',':',datetime.datetime(2016,11,16,17,11,11)) -- ('*',u'order_id',':',2) ('*',u'amount',':',2000) ('*',u'create_time',':',datetime.datetime(2016,11,16,17,11,11)) -- ('*',u'order_id',':',3) ('*',u'amount',':',3000) ('*',u'create_time',':',datetime.datetime(2016,11,16,17,11,11)) () order_count:(1,1,1) order_amount:(1000,2000,3000) order_count_total:3 order_amount_total:6000
ALTERTABLEord_order ADDPARTITION(PARTITIONp201701VALUESIN(201701));
ALTERTABLEord_orderDROPPARTITIONp201601;
MySQL 挂掉要如何处理。
如何实现程序的高可用。
如何记录解析的 log file 和 log pos。
需不需要将解析的数据统一管理和存储。
大家可以考虑一下要如何实现上面的事情。具体如何做我就不说了。
原文来自:http://www.ttlsa.com/database/mysql-binlog-complete-real-time-computing/
本文地址:http://www.linuxprobe.com/binlog-real-time-computing.html编辑:杨鹏飞,审核员:岳国帅
点击左下角查看更多热门技术
本文转载于微信公众号: Linux就该这么学(linuxprobe),更多微信文章请扫描关注公众号:
|