作者:anjia
這是堅持技術寫作計劃(含翻譯)的第41篇,定個小目标999,每周最少2篇。
回想一下之前資料同步一般會使用一些ETL工具,例如 DataX ,StreamSets ,Kettle,sqoop,nifi,當然也可能使用原始的mysqldump進行人肉苦逼同步。因為每個團隊的背景不一樣,沒法簡單的說哪種工具更好,更優,還是需要落地才行。是以本文就不過多介紹不同ETL工具間的優劣了,畢竟PHP是世界上最好的語言。
本文主要講解,如何使用tidb官方的同步工具DM進行資料同步。先搬運一下tidb官方對dm的簡介
DM (Data Migration) 是一體化的資料同步任務管理平台,支援從 MySQL 或 MariaDB 到 TiDB 的全量資料遷移和增量資料同步。使用 DM 工具有利于簡化錯誤處理流程,降低運維成本。
略微吐槽下,tidb的官方技術棧略有點複雜,比如,廣義的 TiDB,一般是指 PD, TiDB, TiKV 這類核心元件(參考 TiDB 整體架構),但是,部署的話,得用ansible部署,監控呢,得學會看官方提供的 Prometheus+Grafana,同步資料的話,又的看 mydumper , loader,syncer, Data Migration ,TiDB Lightning , 管理tidb叢集的話,又會用到一些工具,比如,pd control,pd recover,tikv control,tidb controller,如果要給tidb開啟binlog,用于同步到其他tidb或者mysql叢集,又要研究 Pump,Drainer,binlogctl …
就感覺tidb團隊,一看就是出身大戶人家,看官方建議的叢集配置吧。
- tidb叢集最低配置要求
- dm執行個體配置
- tidb-lighting配置要求(超過200G以上的遷移,建議用tidb-lighting)
- tidb binlog的配置
是以,幾乎每一個用tidb的人,第一件事,都是,如何修改ansible的參數,繞過檢測 [手動滑稽],人嘛,都是,一邊吐槽XX周邊工具太少,又會吐槽XX太多,學不動,像是初戀的少女,等遠方的男友,怕他亂來,又怕他不來,哈哈
對比一下友商的
其實tidb的官方文檔,寫的還挺詳細的,就是不太像是給入門的人看的 [手動捂臉],本文主要是結合我在使用DM過程中,寫一下遇到的問題,以及群内大牛的解答
簡介
DM 簡化了單獨使用mysqldumper,loader,syncer的工作量,從易用性,健壯性和可觀測等方面來看,建議使用DM。
注意一下官方文檔寫的限制條件。
部署DM
參考 使用 DM-Ansible 部署 DM 叢集
如無特殊說明都按照官方文檔操作。
第五步配置互信時,servers 是要部署DM的節點ip,注意目前登入名,確定是tidb(執行
woami
)
vi hosts.ini
[servers]
172.16.10.71
172.16.10.72
172.16.10.73
[all:vars]
username = tidb
執行
ansible-playbook -i hosts.ini create_users.yml -u root -k
時,如果是使用 ssh key的話,可以
ansible-playbook -i hosts.ini create_users.yml -u root -k --private-key /path/to/your/keyfile
第7步配置worker時,需要注意,如果要增量或者全量,并且上遊服務的binlog被删過,并且是gtid格式的,需要執行
show VARIABLES like 'gtid_purged'
如果有值,則需要指定
relay_binlog_gtid
,否則會報
close sync with err: ERROR 1236 (HY000): The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has purged binary logs containing GTIDs that the slave requires.
此時停掉worker後,修改
relay_binlog_gtid
重新開機無效,是需要修改meta檔案的
/tidb/deploy/dm_worker_/relay_log/f5df-11e7-a1dd.000001/relay.meta
感謝 軍軍
另外需要配置
enable_gtid=true
如果不是gtid格式的,則需要修改這個
relay_binlog_name
(在mysql執行
show BINARY logs
)
mysql_password
需要使用
dmctl -encrypt 你的密碼
如果找不到dmctl,確定執行了
ansible-playbook local_prepare.yml
後在
/path/to/dm-ansible/resources/bin/dmctl
dm的worker支援單機多執行個體,也支援單機單執行個體(推薦) ,如果因為資源問題,要開啟單機多執行個體的話,
[dm_worker_servers]
dm_worker1_1 ansible_host=172.16.10.72 server_id=101 deploy_dir=/data1/dm_worker dm_worker_port=8262 mysql_host=172.16.10.81 mysql_user=root mysql_password='VjX8cEeTX+qcvZ3bPaO4h0C80pe/1aU=' mysql_port=3306
dm_worker1_2 ansible_host=172.16.10.72 server_id=102 deploy_dir=/data2/dm_worker dm_worker_port=8263 mysql_host=172.16.10.82 mysql_user=root mysql_password='VjX8cEeTX+qcvZ3bPaO4h0C80pe/1aU=' mysql_port=3306
dm_worker2_1 ansible_host=172.16.10.73 server_id=103 deploy_dir=/data1/dm_worker dm_worker_port=8262 mysql_host=172.16.10.83 mysql_user=root mysql_password='VjX8cEeTX+qcvZ3bPaO4h0C80pe/1aU=' mysql_port=3306
dm_worker2_2 ansible_host=172.16.10.73 server_id=104 deploy_dir=/data2/dm_worker dm_worker_port=8263 mysql_host=172.16.10.84 mysql_user=root mysql_password='VjX8cEeTX+qcvZ3bPaO4h0C80pe/1aU=' mysql_port=3306
注意
server_id=101 deploy_dir=/data1/dm_worker dm_worker_port=8262
别沖突,尤其是
deploy_dir
和
dm_worker_port
第九步,如果部署dm的節點數太多,可以提升并發數
ansible-playbook deploy.yml -f 10
第十步,啟動
ansible-playbook start.yml
上述是簡單操作, 如果涉及到複雜的,例如,擴容,縮容dm節點,重新開機dm-master或者dm-worker,可以參考 DM 叢集操作
配置DM
如何看文檔
配置dm-worker的tasks,三段文檔結合着看
一般場景,使用 Data Migration 簡單使用場景 即可滿足。
庫重命名
庫重命名,将上遊的user,備份成user_north庫。另外,不支援執行個體内databases批量加字首或者字尾。是以,有多少個需要重命名的,就乖乖寫多少個吧
routes:
...
instance-1-user-rule:
schema-pattern: "user"
target-schema: "user_north"
忽略庫或者表
black-white-list:
log-ignored:
ignore-dbs: ["log"] # 忽略同步log庫
ignore-tables:
- db-name: "test" # 忽略同步log庫内的test表
tbl-name: "log"
盡量使用白名單
個人建議盡量使用白名單進行同步,防止因為新增庫dm校驗不通過,導緻task被pause掉。此時的假設是,同步任務是嚴謹的,不應該出現不可控因素。當然這隻是建議。
如果 上遊資料庫有,a,b,c三個庫,前期白名單隻寫了a,b,進行全量+增量同步(all模式),并且task的unit已經是sync(非dump),如果此時要同步庫,此時如果隻是簡單改白名單,然後pause-task,update-task,resume-task,會報表不存在的錯。具體的解決辦法,可以參見 我在tug上提的問題 https://asktug.com/t/db/616 ,感謝 wangxj@pingCAP
black-white-list:
rule-1:
do-dbs: ["~^test-*"] 同步所有test-開頭的庫
忽略drop和truncate操作
畢竟使用DM是用于同步資料,在一定程度上也可以用于災備場景使用,萬一業務庫被人drop,truncate了,tidb這還可以救命,是以建議忽略這些危險操作,有必要的,可以人工去執行。
filters:
...
store-filter-rule:
schema-pattern: "store"
events: ["drop database", "truncate table", "drop table"]
action: Ignore
使用DM Portal生成配置檔案,但是Portal生成的是不支援gtid的,詳見 軍軍 的解釋,詳細使用,參見 DM Portal 簡介
啟動DM
正常操作
參考 管理資料同步任務 使用
./dmctl -master-addr 172.16.30.14
進入互動式指令界面(不支援非互動式的,導緻我在使用中遇到,當報錯資訊特别大時,超過緩沖區,會導緻看不到有效的報錯資訊,check-task xx-task >result.log 這種的不支援,希望後邊能改進下 )
- 啟動任務
注意是task檔案,而不是任務名start-task /path/to/task.yaml
- 查詢任務
task-name是可選的,不填查所有,填了,隻查指定的query-status [task-name]
- 暫停任務
,如果要更新task檔案(update-task) task一定要處于pause狀态(報錯導緻的pause也行)pause-task task-name
- 恢複同步
處于暫停(pause)的任務要恢複,需要使用resume-task ,如果是resume-task task-name
或者full
時unit處于dump狀态的(非load),resume-task時會清空已經dump到本地的檔案,重新拉取(想想200多G的資料庫,到99%了,突然pause了,就肝兒顫)all
- 更新同步任務
注意是task檔案,不是任務名,執行更新操作,必須是pause狀态,是以,盡量别再dump時執行update,要執行也是在前期執行。執行後,需要使用update-task /path/to/task.yaml
啟動已pause的任務resume-task
- 停止任務
stop-task task-name
常見問題
- check通過,start時報錯,或者start也正常,query時報錯,這種錯,有跟沒有差別不大,隻能ssh到worker節點,看日志
/path/to/deploy/log/
-
Couldn't acquire LOCK BINLOG FOR BACKUP, snapshots will not be consistent:Access denied; you need (at least one of) the SUPER privilege(s) for this operation
如果沒有reload權限,會報錯,但是不會終止操作,可以忽略
注意,如果是阿裡雲的rds的話,預設是把reload權限給去掉的。
- sql-mode 不一緻引起的問題,mysql預設的sql-mode是空字元串,參考SQL 模式 ,排查方式
,如果是tidb是新庫,可以SELECT @@sql_mode
如果要改mysql的話,需要寫到set global sql_mode='';
裡,防止重新開機失效。my.ini
- all模式同步資料,如果task狀态已經是sync,此時這個task白名單新增庫或者表會導緻報錯,表不存在,然後task被pause。要麼使用full-task+incremental-task兩個檔案,每次白名單新增時,先更新full-task,再更新incremental-task,要麼直接新啟一個task,用于full更新白名單庫,然後改all的task,重新開機即可。
- 處于dump的任務,一旦pause了,再次resume,會删除已dump的資料檔案,重新拉取
參考資料
- 我的部落格
- 我的掘金
- DataX在有贊大資料平台的實踐
- Data Migration 常見問題
- 使用 DM-Ansible 部署 DM 叢集