Canal v1.1.4版本避坑指南

前提

在忍耐了好久以後,忍不住爆發了,在掘金髮了條沸點(下班時發的):mysql

這是一個使人悲傷的故事,這條情感爆發的沸點好像被屏蔽了,另外小水渠(Canal意爲水道、管道)上線一段時間,不出坑的時候風平浪靜,一旦出坑使人想屎。重點吐槽幾點:git

  • 目前最新的RELEASE版本爲v1.1.4,發佈於2019-9-2,快一年沒更新了。
  • Issue裏面堆積了十分多未處理或者沒有迴應的問題,有很多問題的年紀比較大。
  • master分支常常提交異常的代碼,構建不友好,由於v1.1.4比較多問題,也曾經想過用master代碼手動構建,導入項目以後決定放棄,誰試試誰知道,能夠嘗試對比導入和構建MyBatis的源碼。

這些都只是表象,下面聊聊踩過的坑。github

解析線程阻塞問題

這個基本是每一個使用Canal的開發者的必踩之坑。$CANAL_HOME/conf/canal.properties配置文件中存在一行註釋掉的配置:canal.instance.parser.parallelThreadSize = 16。該配置用於指定解析器實例併發線程數,若是註釋了會致使解析線程阻塞,獲得的結果就是什麼都不會發生。sql

註釋解除便可,建議使用默認值16shell

表結構緩存異常阻塞問題

這是Issue裏面很大部分提問者提到可是久未解決的問題,也就是表結構元數據的存儲問題(配置項裏面使用了tsdb也就是時序數據庫的字眼,下面就稱爲tsdb功能)。數據庫

默認開啓tsdb功能,也就是會經過h2數據庫緩存解析的表結構,可是實際狀況下,若是上游變動了表結構,h2數據庫對應的緩存是不會更新的,這個時候通常會出現神奇的解析異常,異常的信息通常以下:緩存

Caused by: com.alibaba.otter.canal.parse.exception.CanalParseException: column size is not match for table:數據庫名稱.表名稱,新表結構的字段數量 vs 緩存表結構的字段數量;

該異常還會致使一個可怕的後果:解析線程被阻塞,也就是binlog事件不會再接收和解析。這個問題筆者也查看過不少Issue,你們都認爲是一個嚴重的BUG,目前認爲比較可行的解決方案是:禁用tsdb功能(真的夠粗暴),也就是canal.instance.tsdb.enable設置爲false。若是不由用tsdb功能,一旦出現了該問題,必需要先中止Canal服務,接着刪除$CANAL_HOME/conf/目標數據庫實例標識/h2.mv.db文件,而後啓動Canal服務。服務器

由於這個比較坑的問題,筆者在生產禁用了tsdb功能,而且添加了DDL語句的處理邏輯,直接打到釘釘預警上而且@整個羣的人。架構

每次看到這個預警都心驚膽戰。併發

日誌問題

若是恰好須要定位的binlog位點處於比較靠後的文件,文件數量比較多,會瘋狂打印尋位的日誌。以前嘗試太重啓一會兒打印了幾GB日誌,超過99%是定位binlog文件和position的日誌行。能夠考慮經過修改$CANAL_HOME/conf/logback.xml(並不建議,不清楚源碼容易形成其餘新的問題)配置或者指定$CANAL_HOME/conf/目標數據庫實例標識/instance.properties的下面幾個屬性手動定位解析的起點:

canal.instance.master.journal.name=binlog的文件名
canal.instance.master.position=binlog的文件中的位點
canal.instance.master.timestamp=時間戳
canal.instance.master.gtid=gtid的值

以上的手動定位解析的起點的屬性須要在下次重啓Canal以前更新或者註釋掉,不然會形成從新解析或者找不到文件的嚴重後果!!!

反正每次重啓Canal服務都驚心動魄,沒有一個開源軟件可讓人有這種感受。由於生產的服務器磁盤不是很充足,選配的時候只買了100GB,並且考慮到這些日誌本質上沒有太大意義,因而只能按期上去刪日誌,前期是手動刪,後來以爲麻煩寫了個Shell腳本定時刪除久遠的日誌文件。

雲RDS MySQL的使用問題

若是恰好使用了阿里雲的RDS MySQL,那麼有可能會遭遇更大的坑。主要問題是:

  • RDS MySQL有磁盤空間優化規則,觸發了規則會把binlog文件上傳到OSS,而後刪除本地的binlog文件。
  • Canal的文檔來看,會自動拉取OSS上的binlog文件進行解析,讓使用者無感知,可是此功能有BUG,一直沒法正常使用。
  • RDS MySQL是一個暗箱,出了問題只能經過MySQL的相關查詢去定位問題,沒有辦法進去服務器查看真實的現場。

命中了這個問題,通常​出現的異常是:

.................. sqlstate = HY000 errmsg = Could not find first log file name in binary log index file

能夠基本確認這個功能是存在缺陷的,例如這裏有個Issue-2596

目前筆者的作法以下:

  • 徹底棄用Canal拉取OSS上的binlog文件的功能。
  • RDS MySQL儘量擴容一下磁盤,調整策略讓儘量多的binlog文件儘量久地保留在本地,讓它們被徹底解析後再手動上傳或者命中了過時規則後自動上傳,這期間有不少東西須要額外收取費用,具體須要自行權衡。

讀取和解析OSS上的binlog文件在目前(2020-08-05)的master分支上依然有BUG,想手動構建master分支的夥伴建議放棄幻想。

這個問題的嚴重後果是:有比較大的可能性致使某段binlog文件解析徹底缺失,除非能夠把binlog文件從新塞回去RDS MySQL裏面,不然須要作上下游手動同步功能。

to be continue

除此以外,要注意Canal最好作主備部署,提交位點和集羣管理建議使用Zookeeper,而服務模式(canal.serverMode,目前支持tcpkafkarocketmq)建議選用Kafkamaster分支上有RabbitMQ的鏈接器支持,若是想嚐鮮能夠手動構建一下),而且每一個節點的資源要求比較高,筆者生產上每一個節點使用了2C8G低主頻的ECS,感受有點壓不住,特別時重啓實例的時候若是須要從新定位binlog位點,CPU在一段時間內使用率會飆高。

筆者發現了阿里雲的DTS就是使用了Canal做爲基礎中間件進行數據同步的,說明它有被投產到實際應用場景中,真不但願它最終演變成廢棄的KPI任務項目。不知道日後還會遇到多少問題,若是碰到了也會持續更新本避坑指南。

(本文完 c-2-d e-a-20200805)

這是公衆號《Throwable》發佈的原創文章,收錄於專輯《架構與實戰》。

相關文章
相關標籤/搜索