Skip to content

canal整体性能优化 #726

Closed
Closed
@agapple

Description

@agapple
Member

之前有较多的小伙伴, 反馈在大规模数据DML变更时消费速度有点跟不上, 反馈的问题列表:

  1. Mysql产生的binlog,大量数据的时候,同步到Canal慢,这个怎么解决? #672
  2. Canal Server 解析性能问题 #547
  3. 当数据库有大量的删除时,canal解析变慢 #355
  4. canal收集 由一条update语句更新多行 产生的binlog的速度很慢 什么原因呢? #267

这里会做一个相对完整的测试,进行针对性的优化,同时也非常欢迎大家的参与和代码MR,一起努力解决好性能和稳定性的问题. ps. 1.0.26会是一个里程碑式的版本。


最后的优化结果:https://github.com/alibaba/canal/wiki/Performance

image

Activity

added this to the v1.0.26 milestone on Jun 30, 2018
self-assigned this
on Jun 30, 2018
zwangbo

zwangbo commented on Jul 2, 2018

@zwangbo

赞赞赞

mjjian0

mjjian0 commented on Jul 2, 2018

@mjjian0

期待ing,期待ing

lcybo

lcybo commented on Jul 2, 2018

@lcybo
Collaborator

赞!
我先来抛个砖,说说以前遇到的issue和一些思路:
场景是,使用load backup file的方式灌数据,同时使用canal进行同步。
每个表一个或多个文件,由于每个文件中的行都同属于一张表的同一事件(INSERT),mysql-binlog会merge一定量的行(取决于binlog-row-event-max-size)到同一event。
*单句DML影响到多行数据的情况应该也适用。
压缩的event经过解析为protobuf对象,内存占用急剧膨胀,造成fgc频繁,甚至oom。
在MySQL 5.6的版本,官方默认将binlog-row-event-max-size从1024调高到了8192。
当时我们通过将binlog-row-event-max-size设回1024,问题被绕过。
如果将server/client 的netty3升级为4,用PooledByteBuf应该可以缓解一小部分。但大头还是protobuf这个memory hogs.

lcybo

lcybo commented on Jul 3, 2018

@lcybo
Collaborator

补充一下,ringbuffer size被设置为4096。内存是4g.由于load backup file以后就是平稳的正常traffic。因此并不想调整内存或进一步减小ringbuffer

added a commit that references this issue on Jul 3, 2018

fixed issue #726, 去掉socket receiveBuffer/sendBuffer的设置,影响网络吞吐量

agapple

agapple commented on Jul 3, 2018

@agapple
MemberAuthor

第一步网络优化(只做header解析,识别包大小、位点等信息,不做具体的记录级别解析)
结果:默认设置的32k的socket buffer,针对大吞吐量传输时有点过小,去掉了默认设置,让socket自我协调,默认在24c96g的物理机上测试,receiveBuffer协调结果为180k.

调整前后的性能吞吐量对比: 18MB VS 117MB,提供6倍多,socket buffer优化之后基本可以跑满网卡

added a commit that references this issue on Jul 3, 2018

fixed issue #726 优化时间类型的解析,速度从20MB提升到45MB

agapple

agapple commented on Jul 3, 2018

@agapple
MemberAuthor

第二步优化解析的能力,跑了下简单的对象解析(不做protobuf的对象构建),刚开始速度是20MB,主要优化了时间字段的解析上,提升到了45MB.

目前遇到瓶颈了,观察系统的负载cpu最高在1.5核左右,jvm gc主要集中在young区,下一步的优化思路:多线程并行解析,最大化的使用系统负载进行优化

agapple

agapple commented on Jul 3, 2018

@agapple
MemberAuthor

第三步整体并发模型设计,按照前面的优化网络和对象解析,瓶颈都在对象的深度解析上,如果要最大化性能,必须得引入并发设计,整体设计思路如下:

image

基于ringbuffer的并发模型,整个过程会分为4个阶段,多个阶段之间互相隔离和依赖,把最耗瓶颈的解析这块采用多线程的模型进行加速,预计整个优化完成,整个解析可以跑满整个千兆网卡.

ps. 如果各位有万兆网卡的机型,到时候可以也帮忙跑一下效果

agapple

agapple commented on Jul 3, 2018

@agapple
MemberAuthor

@lcybo 针对内存占用的问题,你有什么优化建议么?换掉protobuf?

lcybo

lcybo commented on Jul 3, 2018

@lcybo
Collaborator

个人一点不成熟的想法:
因为不跨语言,可以用基于protobuf和java的protostuff。
相对来说,优点:

  • 比protobuf快,占用内存更少,相同的data size。
  • 可以使用POJO,不用proto文件。protobuf的generated code对人太不友好了。

不足的地方:

  • 社区不太活跃。
  • 待补充哈哈。

贴出一些细节:
// Re-use (manage) this buffer to avoid allocating on every serialization
LinkedBuffer buffer = LinkedBuffer.allocate(512);
对比protobuf:
byte[] result = new byte[this.getSerializedSize()];

此外,POJO还可以参考netty的Recycler或其他的对象池,理论上,ringbuffer中event占用Entry对象的峰值就是ObjectPool需要缓存的对象个数。
ProtostuffIOUtil.mergeFrom(protostuff, fooParsed, schema); //fooParsed是可以提供的,反序列化可以从ObjectPool受益。
当然这么做代码会复杂些。

agapple

agapple commented on Jul 3, 2018

@agapple
MemberAuthor

byte[]的复用倒是有, 基于ObjectPool的思路以前还真没考虑过, 对象里的各种嵌套结构体也不太一样, 不太理解复用的原理 @lcybo

42 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

    Development

    No branches or pull requests

      Participants

      @agapple@wq19880601@francisoliverlee@littleneko@f-zhao

      Issue actions

        canal整体性能优化 · Issue #726 · alibaba/canal