本人相关文章
docke 安装canal-admin ui管理canal-server(系列一)
canal-admin投递binglog到kafka,多进程消费kafka同步数据变更(系列二)
相关资料
canal信息新增上直接投递到mq的配置
- 原来的数据库配置不变 可以登陆管理地址直接查看配置信息
# 表过滤正则
canal.instance.filter.regex = test\\.test.*
# 投递到单个topic
canal.mq.topic = test_binlog_icr
#这里是多个动态topic配置,暂时不用这么多topic
#canal.mq.dynamicTopic = topic:test\\.qa_.*
canal.mq.partition=0
# hash6个分区
canal.mq.partitionsNum = 6
# 根据主键散裂分区 可保证数据热点问题不会出现,并且保证同一个主键下变更记录在同一个分区,而且我们只是做触发记录不是直接根据值做处理根据表散列就会出现有的分区很多数据 有的表没啥访问
canal.mq.partitionHash = .*\\..*:$pk$
- 关于分区mq配置 可参考官方文档:https://github.com/alibaba/canal/wiki/Canal-Kafka-RocketMQ-QuickStart#mq%E9%A1%BA%E5%BA%8F%E6%80%A7%E9%97%AE%E9%A2%98
topic 和 group.id 使用
- topic 使用 test_binlog_icr 相关的mysql binlog 全部投递到这个主题 (本主题可以被多个不同的消费组去消费)
- 消费组 search_incr 检索同步消费组 目前订阅了 test_binlog_icr 这一个主题,后面增加其他检索主题也可以继续订阅
kafka同步
- test_binlog_icr 设置6分区 可开启6消费进程同步消费 看消费延迟上是否会缩短,还是会增长,理论上会缩短 (因为canal新版本性能有150%的提升,用kafka 6个进程去消费)
- 已经默认关闭自动提交位移,请使用例子的 commit 或者 commitAsync 在代码逻辑执行完成手动提交位置
原因:自动提交 比如设置1000ms提交一次 就是1秒,这个时候消费了3个,但是未提交,程序代码崩溃了,就会出现3个重复消费,位移不准确的问题,如果是在业务上也可以通过自己业务做幂等逻辑判断,日志同步的时候不好做判断 - 包装的客户端\Lib\Mq\RdKafkaMq::getClient() 简单的例子,有需要的可以留言问博主索要
/**
* 获取kafka消费者
* 获取后 通过consume(毫秒ms)获取消费消息 commit() 或者 commitAsync() 提交当前位移
* 也可以设置多少毫秒自动提交位移enable.auto.commit=true auto.commit.interval.ms = 1000ms
* 这里建议逻辑执行成功后手动提交位移
* 更多配置参数和详解,建议参考如下官方文档
* @link https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md
* @param string $groupId 消费组id
* @param array $topics 订阅的主题列表
* @param array $config kafka配置 如果传入则设置该配置
* @return \RdKafka\KafkaConsumer
*/
public function getConsumer(string $groupId,array $topics,array $config = [])
{
$confs = array_merge([
//kafka broker 列表
'metadata.broker.list' => $this->brokerList,
//当没有初始偏移量时,从哪里开始读取 earliest从头,latest从最后,设置默认从最后消费
'auto.offset.reset' => 'latest',
//配置groud.id 具有相同 group.id 的consumer将会处理不同分区的消息,消费者进程的数量多于分区的数量是没有意义的。
'group.id' => $groupId,
//自动提交位移 默认设置为不提交
'enable.auto.commit' => 'false',
],$config);
$kafkaConf = new Conf();
foreach ($confs as $confKey => $conf) {
$kafkaConf->set($confKey,$conf);
}
// 当有新的消费进程加入或者退出消费组时,kafka 会自动重新分配分区给消费者进程,这里注册了一个回调函数,当分区被重新分配时触发
$kafkaConf->setRebalanceCb($this->getRebalanceCallBack($groupId));
$kafkaConsumer = new KafkaConsumer($kafkaConf);
$kafkaConsumer->subscribe($topics);
return $kafkaConsumer;
}
- 简单的消费代码
$kafkaMq = \Lib\Mq\RdKafkaMq::getClient();
$kafkaConsumer = $kafkaMq->getConsumer('search_incr',['test_binlog_icr'],['auto.offset.reset' => 'earliest']);
//需要等待分区分配
while (true) {
$message = $kafkaConsumer->consume(120*1000);
switch ($message->err) {
case RD_KAFKA_RESP_ERR_NO_ERROR:
var_dump($message->partition.":".$message->offset);
//执行逻辑并且确定没问题则提交位移
$kafkaConsumer->commit();
break;
case RD_KAFKA_RESP_ERR__PARTITION_EOF:
echo "No more messages; will wait for more\n";
break;
case RD_KAFKA_RESP_ERR__TIMED_OUT:
echo "Timed out\n";
break;
default:
throw new \Exception($message->errstr(), $message->err);
break;
}
}
查看所有topic
- –bootstrap-server 192.168.3.101:9092 参数为server地址
./bin/kafka-topics.sh --bootstrap-server 192.168.3.101:9092 --list
创建topic
- 创建主题时用到三个参数:
- –topic :主题名字
- –partitions :分区数量
- –replication-factor :副本因子 几个副本(不能超过集群broker量 比如3集群 最多3)
./bin/kafka-topics.sh --bootstrap-server 192.168.3.101:9092 --create --topic test_binlog_icr --partitions 6 --replication-factor 1
删除topic
./bin/kafka-topics.sh --bootstrap-server 192.168.3.101:9092 --delete --topic test_binlog_icr
查看所有消费组
./bin/kafka-consumer-groups.sh --bootstrap-server 192.168.3.101:9092 --list
创建消费组
- 新版本连接时会自动创建 不需要提前创建
删除消费组
- 新版本所有成员离开会自动处理不用删除