1、前言
搁在过去的文章当中,或者应该称作笔记,我只会记录一些命令和代码,是不会或者很少写几个注释,更别说写一些文章背景,软件版本,问题背景,需求梳理,解决思路,收获小结等等,按照上面的写作方法存在了一些问题,比如,无从知道前因后果,无法知晓适用环境,无法知道以后需要规避哪些风险,所以过去写的文章顶多能拿来作为实施的参考,没有更多的价值和作用。
痛定思痛之后,我决定从这一篇文章开始,按照写文章的正确思路,逐一表达清楚,争取让读者朋友一眼看懂,同时为今后回顾的时候减少熟悉前前后后关联事情的时间和精力。下面进入今天的正文【Debezium】,同时也要感谢各位朋友耐心阅读上面这番唠叨话。
2、本文背景
前不久大数据小组的同学根据业务部门的需求提出需要订阅Postgresql数据,于是乎大家一起对于订阅方案和工具进行全网找资料和调研与实验,本着尽可能少花钱的宗旨,找到了【Debezium】,经过了多次环境搭建调试和订阅验证测试,成功实现了这个任务,完成了业务部门的需求。
3、为什么选择Debezium
在实现Postgres实时同步数据到Postgres的任务中,我们遇到了一个大麻烦,【复制槽堆积】,这困扰我们很长一段时间,我们用了国内一款云版本同步产品【Tapdata】,从使用体验来说操作真的非常便捷,点点点就行,但唯独当时无法解决的问题是【复制槽堆积】,我们用的是阿里云RDS的Postgres-12版本。为此还不得已让找了ava开发同学开发了一个RPA工具来定时启动任务,定时关闭任务,过程非常曲折。经过实验测试,debezium缓解了【复制槽堆积】问题,但是我们忽略了debezium本身的使用场景,数据订阅,数据送达的目的地是消息中间件。为此我们的Postgres同步还是跑着RPA,这是题外话,介绍这些主要是为了说明一下在什么情况下我们选择了Debezium。
4、实验环境软件版本
操作系统 | CentOS 7.9 |
---|---|
Docker-CE | docker-ce-18.09.9-3.el7 |
Debezium | debezium/connet:2.0; debezium/debezium-ui:2.0 |
Kafka | bitnami/kafka:3.4.0 |
Postgresql | postgres:12.14 |
Zookeeper | zookeeper:3.8.1 |
5、实验完整步骤
5.1、Kafka
5.1.1、快速搭建
docker run -d --name zookeeper -p 2181:2181 -t zookeeper:3.8.1
docker run -d --name kafka --publish 9092:9092 --link zookeeper --env KAFKA_ZOOKEEPER_CONNECT=172.18.12.182:2181 --env KAFKA_ADVERTISED_HOST_NAME=172.18.12.182 --env KAFKA_ADVERTISED_PORT=9092 --volume /etc/localtime:/etc/localtime bitnami/kafka:3.4.0
5.1.2、topic规划
不调整kafka参数的时候,topic是支持自动创建的
debezium将会自动创建下面几个tpic
- debezium.public.debezium_heartbeat
- my_connect_statuses
- my_connect_offsets
- my_connect_configs
5.2、Postgres
5.2.1、快速搭建和
docker run -it --name postgres --restart always -e POSTGRES_PASSWORD='abc123' -e ALLOW_IP_RANGE=0.0.0.0/0 -v /home/postgres/data:/var/lib/postgresql -p 55433:5432 -d postgres
5.2.2、数据与用户准备
#触发心跳表更新的普通用户
create user debezium01 PASSWORD ‘debezium01’;
#在pgadmin4打开要维护db的查询窗口
grant all privileges on public.public.debezium_heartbeat to debezium01;
#心跳表
create table public.public.debezium_heartbeat(id int primary key,last_ts timestamp);
insert into public.public.debezium_heartbeat values (555333,NOW());
update public.public.debezium_heartbeat set last_ts = NOW() where id = 555333;
5.3、Debezium
5.3.1、部署
docker run -it -d --name connect \
--restart=unless-stopped \
-p 8084:8083 \
-e GROUP_ID=1001 \
-e CONFIG_STORAGE_TOPIC=my_connect_configs \
-e OFFSET_STORAGE_TOPIC=my_connect_offsets \
-e STATUS_STORAGE_TOPIC=my_connect_statuses \
-e BOOTSTRAP_SERVERS=172.18.12.182:9092 \
debezium/connect:2.0
docker run -it -d --name debezium-ui \
--restart=unless-stopped \
-p 8085:8080 \
-e KAFKA_CONNECT_URIS=http://172.18.12.182:8084 \
debezium/debezium-ui:2.0
5.3.2、配置调整
\#更新2个性能的参数和添加1个上报心跳的参数
docker ps获取container id
假设是b2f44abba434
\#从容器里面下载配置文件到本地
docker cp b2f44abba434:/kafka/config/connect-distributed.properties ./
\#修改参数值
sed -i "s/key.converter.schemas.enable=true/key.converter.schemas.enable=false/g" connect-distributed.properties
sed -i "s/value.converter.schemas.enable=true/value.converter.schemas.enable=false/g" connect-distributed.properties
echo "heartbeat.interval.ms=3000" >> connect-distributed.properties
\#拷贝文件到容器里面进行覆盖
docker cp connect-distributed.properties b2f44abba434:/kafka/config/
\#重启加载新的配置文件
docker restart b2f44abba434
\#下载和验证
docker cp b2f44abba434:/kafka/config/connect-distributed.properties ./
grep -Ev "^$|#" connect-distributed.properties | grep "heartbeat.interval.ms"
5.3.3、创建订阅用的高权限账号
#pg数据库创建管理员账号给debezium订阅用
sync_debezium
sync_debezium
5.3.4、注册订阅任务
curl -i -X POST -H "Content-Type:application/json" -H "Accept:application/json" 172.18.12.182:8084/connectors/ -d '{
"name": "test-lab",
"config": {
"connector.class": "io.debezium.connector.postgresql.PostgresConnector",
"connector.displayName": "PostgreSQL",
"database.user": "sync_debezium",
"database.dbname": "test-lab",
"slot.name": "debezium_test-lab",
"slot.drop.on.stop": "true",
"schema.include.list": "public",
"connector.id": "postgres",
"database.port": "5432",
"plugin.name": "pgoutput",
"topic.prefix": "debezium",
"database.hostname": "172.18.12.182",
"database.password": "sync_debezium",
"table.include.list": "public.debezium_heartbeat"}}'
#注意schema.include.list,table.include.list
5.4、循环执行update出发事件推进
5.4.1、shell脚本
#shell脚本
[root@tools debezium]# cat auto_update_public_debezium_heartbeat.sh
#!bin/bash
#数据库bin命令存放目录
pg_path="/bin"
#执行的SQL存放目录
sql_path="/opt/debezium"
db_host='172.18.12.182'
db_port='5432'
db_username='debezium01'
db_name='test-lab'
step=3 #间隔的秒数,不能大于60
for (( i = 0; i < 116; i=(i+step) )); do
echo '['$(date "+%Y-%m-%d %H:%M:%S")'] 每3s更新<debezium_heartbeat>表'
echo '['$(date "+%Y-%m-%d %H:%M:%S")'] 开始更新'
PGPASSWORD=debezium01 $pg_path/psql -h $db_host -p $db_port -U $db_username --dbname $db_name1 -e -f $sql_path/'update_public_t3.sql'
echo '['$(date "+%Y-%m-%d %H:%M:%S")'] 完成更新'
sleep $step
done
exit 0
5.4.2、sql文件
vim update_public_debezium_heartbeat.sql
update public.t3 set last_ts = now() where id = 555333;
5.4.3、cron任务
*/2 * * * * /bin/bash /opt/debezium/auto_update_public_debezium_heartbeat.sh
5.5、观察wal文件自动清理
- 阿里云rds–pg监控与报警–增强监控–ReplicationSlot延迟
- tools主机运行shell脚本观察运行情况:
watch -n 1 ‘ps -ef|grep auto_update_public_t3.sh’
tailf /var/log/cron - pgadmin4上面select观察时间戳的变化: select * from public.t3;
6、收获
postgresql:
创建用户、分配权限
存储过程创建、使用、删除
修改表结构,新增字段
插入和更新数据
kafka:
topic查看、创建、删除
docker快速部署kafka单机环境
简单生产和消费测试
debezium:
pg到kafka订阅实现流程
7、小结
Debezium的实践过程让我收获了很多思路上的东西,比如
7.1、复制堆积要通过上报lsn推动复制向前移动,来实现wal文件自动回收
7.2、复制槽保证了事件的持续订阅不丢失,但是当没有事件触发的时候,仍然会生成一个个16M的wal文件
7.3、在调研的时候,要做充分的场景设计和严格的测试,更全面的了解软件工作中会面临的问题,减少在生产环境里面遇到未知问题(当然这个设想本身是太理想主义了)
8、感谢
感谢各位朋友耐心阅读,希望本文能带去一些灵感和解决问题的思路,IT技术的路上,有你有我,我们不会孤独。
9、参考资料
(光速上手)Docker搭建kafka单机版_芸香科代表的博客-CSDN博客