应用场景
1、实时同步mysql数据到另外一个数据仓库(ES、另一个mysql)
2、电商场景下的实时报表计算展示
3、。。。。
环境搭建过程》》》》【mysql+kafka+kafka-eagle】
消费者 demo_1
1、tcp工作模式下的 canal
import time
from canal.client import Client
from canal.protocol import EntryProtocol_pb2
# 建立与canal服务端的连接
client = Client()
client.connect(host='127.0.0.1', port=11111) # canal服务端部署的主机IP与端口
client.check_valid(username=b'canal', password=b'canal') # 自行填写配置的数据库账户密码
# destination是canal服务端的服务名称, filter即获取数据的过滤规则,采用正则表达式
client.subscribe(client_id=b'12', destination=b'test_canal', filter=b'db.table,db.table2')
while True:
message = client.get(100)
# entries是每个循环周期内获取到数据集
entries = message['entries']
for entry in entries:
entry_type = entry.entryType
if entry_type in [EntryProtocol_pb2.EntryType.TRANSACTIONBEGIN, EntryProtocol_pb2.EntryType.TRANSACTIONEND]:
continue
row_change = EntryProtocol_pb2.RowChange()
row_change.MergeFromString(entry.storeValue)
event_type = row_change.eventType
header = entry.header
# 数据库名
database = header.schemaName
# 表名
table = header.tableName
event_type = header.eventType
# row是binlog解析出来的行变化记录,一般有三种格式,对应增删改
for row in row_change.rowDatas:
format_data = dict()
# 根据增删改的其中一种情况进行数据处理
if event_type == EntryProtocol_pb2.EventType.DELETE:
format_data['before'] = dict()
for column in row.beforeColumns:
format_data['before'][column.name] = column.value
elif event_type == EntryProtocol_pb2.EventType.INSERT:
format_data['after'] = dict()
for column in row.afterColumns:
format_data['after'][column.name] = column.value
else:
format_data['before'] = dict()
format_data['after'] = dict()
for column in row.beforeColumns:
format_data['before'][column.name] = column.value
for column in row.afterColumns:
format_data['after'][column.name] = column.value
# data即最后获取的数据,包含库名,表明,事务类型,改动数据
data = dict(
db=database,
table=table,
event_type=event_type,
data=format_data,
)
print(data)
time.sleep(1)
client.disconnect()
直接执行,过滤规则中的表发生数据操作时就会打印一条Binlog
{'db': 'db, 'table': 'table1', 'event_type': 1, 'data': {'after': {'id':'01' ,'name':'test'}}}
对应发生变化的数据库名、表、变化事件(增删改)、具体字段数据
消费者 demo_2
2、Kafka工作模式下的Canal
kafka_client.py
from django.core.management.base import BaseCommand
from kafka import KafkaConsumer
import handel_method
import json
consumer = KafkaConsumer('topic_name', value_deserializer=json.loads, bootstrap_servers=['127.0.0.1:9092'])
for msg in consumer:
print(msg)
执行起来就是一个死循环,不断的读取队列的消息
整合Django
方案:自定义django命令
特定django APP下新建目录management,在此目录下再新建commands,commands目录下新建处理handler.py:
from django.core.management.base import BaseCommand
from kafka import KafkaConsumer
from test import handel_method
import json
class Command(BaseCommand):
def handle(self, *args, **options):
consumer = KafkaConsumer('topic', bootstrap_servers=['127.0.0.1:9092'],
value_deserializer=json.loads, group_id="test-consumer-group")
for message in consumer:
handel_method(message)
handel_method则按自身业务需求编写
运行方法:
python manage.py runserver ## 启动django服务
python manage.py handler
部署:
这里的部署方案以docker部署django项目为例。
docker-composer.yml:
version: '3'
services:
django-server:
## 你的django 项目部署配置
kafka-handler: ## 消费者部署
#......
command: python manage.py handler