簡介
TiDB 是 PingCAP 公司受 Google Spanner / F1 論文啟發而設計的開源分布式 HTAP (Hybrid Transactional and Analytical Processing) 數據庫, 結合了傳統的 RDBMS 和 NoSQL 的最佳特性。TiDB 兼容 MySQL,支持無限的水平擴展,具備強一致性和高可用性。 TiDB 的目標是為 OLTP (Online Transactional Processing) 和 OLAP (Online Analytical Processing) 場景提供一站式的解決方案。
TiDB整體架構

TiDB 集群主要分為三個組件:
-
TiDB Server
TiDB Server 負責接收 SQL 請求,處理 SQL 相關的邏輯,並通過 PD 找到存儲計算所需數據的 TiKV 地址, 與 TiKV 交互獲取數據,最終返回結果。 TiDB Server 是無狀態的,其本身並不存儲數據,只負責計算,可以無限水平擴展, 可以通過負載均衡組件(如LVS、HAProxy 或 F5)對外提供統一的接入地址。
-
PD Server
Placement Driver (簡稱 PD) 是整個集群的管理模塊,其主要工作有三個: 一是存儲集群的元信息(某個 Key 存儲在哪個 TiKV 節點); 二是對 TiKV 集群進行調度和負載均衡(如數據的遷移、Raft group leader 的遷移等);三是分配全局唯一且遞增的事務 ID。
PD 是一個集群,需要部署奇數個節點,一般線上推薦至少部署 3 個節點。
-
TiKV Server
TiKV Server 負責存儲數據,從外部看 TiKV 是一個分布式的提供事務的 Key-Value 存儲引擎。存儲數據的基本單位是 Region, 每個 Region 負責存儲一個 Key Range (從 StartKey 到 EndKey 的左閉右開區間)的數據, 每個 TiKV 節點會負責多個 Region 。TiKV 使用 Raft 協議做復制,保持數據的一致性和容災。 副本以 Region 為單位進行管理,不同節點上的多個 Region 構成一個 Raft Group,互為副本。 數據在多個 TiKV 之間的負載均衡由 PD 調度,這里也是以 Region 為單位進行調度。
安裝與部署
單節點方式快速部署(適用於功能測試,預覽)
執行步驟:
# 下載壓縮包 wget http://download.pingcap.org/tidb-latest-linux-amd64.tar.gz wget http://download.pingcap.org/tidb-latest-linux-amd64.sha256 # 檢查文件完整性,返回 ok 則正確 sha256sum -c tidb-latest-linux-amd64.sha256 # 解開壓縮包 tar -xzf tidb-latest-linux-amd64.tar.gz cd tidb-latest-linux-amd64
在獲取 TiDB 二進制文件包后,我們可以在單機上面,運行和測試 TiDB 集群,請按如下步驟依次啟動 PD,TiKV,TiDB。
注意:以下啟動各個應用程序組件實例的時候,請選擇后台啟動,避免前台失效后程序自動退出。
- 步驟一,啟動 PD
./bin/pd-server --data-dir=pd \
--log-file=pd.log
- 步驟二,啟動 TiKV
./bin/tikv-server --pd="127.0.0.1:2379" \ --data-dir=tikv \ --log-file=tikv.log
- 步驟三,啟動 TiDB
./bin/tidb-server --store=tikv \
--path="127.0.0.1:2379" \ --log-file=tidb.log
- 步驟四,使用 MySQL 客戶端連接 TiDB:
mysql -h 127.0.0.1 -P 4000 -u root -D test
Ansible 部署集群(強烈推薦)
准備機器
測試部署,下列所有機器均由
Virtual Box生成的虛擬環境,生產環境中請參考官方文檔配置。 注意開啟虛擬機的 specific IP,eg:config.vm.network "private_network", ip: "192.168.12.10"。
- 部署目標機器若干
- 建議 4 台及以上,TiKV 至少 3 實例(本教程 3 實例),且與 TiDB、PD 模塊不位於同一主機,詳見部署建議
-
推薦安裝 CentOS 7.3 及以上版本 Linux 操作系統(本教程使用 ubuntu 16.04),x86_64 架構(amd64), 數據盤請使用 ext4 文件系統,掛載 ext4 文件系統時請添加 nodelalloc 掛載參數
編輯
/etc/fstab文件,添加nodelalloc掛載參數:# vi /etc/fstab /dev/nvme0n1 /data1 ext4 defaults,nodelalloc,noatime 0 2使用以下命令 umount 掛載目錄並重新掛載:
# umount /data1 # mount -a通過以下命令確認是否生效:
# mount -t ext4 /dev/nvme0n1 on /data1 type ext4 (rw,noatime,nodelalloc,data=ordered) - 機器之間內網互通,防火牆如 iptables 等請在部署時關閉
-
機器的時間、時區設置一致,開啟 NTP 服務且在正常同步時間
注: Ubuntu 系統請安裝 ntpstat 軟件包
$ ntpstat unsynchronised # NTP 服務未正常同步 $ ntpstat Unable to talk to NTP daemon. Is it running? # NTP 服務未正常運行 sudo systemctl status ntp.service # 查看 ntp 服務運行狀態 -
創建 tidb 普通用戶 (本教程使用 vagrant 用戶)作為程序運行用戶,tidb 用戶可以免密碼 sudo 到 root 用戶
# useradd tidb # passwd tidb # visudo tidb ALL=(ALL) NOPASSWD: ALL本教程中
vagrant用戶默認免密 sudo 到 root 用戶
- 部署中控機器一台
- 中控機可以是部署目標機器中的某一台。
- 推薦安裝 CentOS 7.3 及以上版本 Linux 操作系統(默認包含 Python 2.7,本教程使用 ubuntu 16.04)。
- 該機器需開放外網訪問,用於下載 TiDB 及相關軟件安裝包。
-
配置 ssh authorized_key 互信,在中控機上可以使用 tidb 用戶(本教程使用 vagrant 用戶)免密碼 ssh 登錄到部署目標機器
# vagrant 用戶 $ ssh-keygen -t rsa Generating public/private rsa key pair. Enter file in which to save the key (/home/tidb/.ssh/id_rsa): Created directory '/home/tidb/.ssh'. Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/tidb/.ssh/id_rsa. Your public key has been saved in /home/tidb/.ssh/id_rsa.pub. The key fingerprint is: SHA256:eIBykszR1KyECA/h0d7PRKz4fhAeli7IrVphhte7/So tidb@172.16.10.49 The key's randomart image is: +---[RSA 2048]----+ |=+o+.o. | |o=o+o.oo | | .O.=.= | | . B.B + | |o B * B S | | * + * + | | o + . | | o E+ . | |o ..+o. | +----[SHA256]-----+ sudo cat ~/.ssh/id_rsa.pub authorized_keys # 依次執行以下命令,將 192.168.12.10 替換成目標機器的ip,按提示輸入部署目標機器 vagrant 用戶密碼, # 執行成功后即創建好 ssh 互信,其他機器同理。 ssh-copy-id -i ~/.ssh/id_rsa.pub 192.168.12.10 # 驗證 ssh 互信 ssh 192.168.12.10 # 不需要輸入密碼並登錄成功
在中控機上下載 TiDB-Ansible
以 vagrant 用戶登錄中控機並進入 /home/vagrant 目錄,使用以下命令從 Github TiDB-Ansible 項目 上下載 TiDB-Ansible 相應版本, 默認的文件夾名稱為 tidb-ansible,以下為各版本下載示例,版本選擇可以咨詢官方。
# 下載 2.0 GA 版本: git clone -b release-2.0 https://github.com/pingcap/tidb-ansible.git # 下載 master 版本: git clone https://github.com/pingcap/tidb-ansible.git
本教程為master版本
在中控機上安裝 Ansible 及其依賴
$ sudo apt-get install python-pip curl $ cd tidb-ansible $ sudo pip install -r ./requirements.txt
pip install 時可能會報Python locale error: unsupported locale setting,執行下列命令:
export LC_ALL="en_US.UTF-8" export LC_CTYPE="en_US.UTF-8" sudo dpkg-reconfigure locales
分配機器資源,編輯 inventory.ini 文件
sudo vim ~/tidb-ansible/inventory.ini
配置如下:(更換ip為你的目標機器ip,192.168.12.22為中控機器ip,其他為目標機器ip)
## TiDB Cluster Part [tidb_servers] 192.168.12.22 [tikv_servers] 192.168.12.10 192.168.12.2 192.168.12.3 [pd_servers] 192.168.12.22 [spark_master] [spark_slaves] ## Monitoring Part # prometheus and pushgateway servers [monitoring_servers] 192.168.12.22 [grafana_servers] 192.168.12.22 # node_exporter and blackbox_exporter servers [monitored_servers] 192.168.12.22 192.168.12.10 192.168.12.2 192.168.12.3 [alertmanager_servers] ## Binlog Part [pump_servers:children] tidb_servers ## Group variables [pd_servers:vars] # location_labels = ["zone","rack","host"] ## Global variables [all:vars] deploy_dir = /home/vagrant/deploy ## Connection # ssh via normal user ansible_user = vagrant cluster_name = test-cluster tidb_version = latest # process supervision, [systemd, supervise] process_supervision = systemd # timezone of deployment region timezone = Asia/Shanghai set_timezone = True enable_firewalld = False # check NTP service enable_ntpd = True set_hostname = False ## binlog trigger enable_binlog = False # zookeeper address of kafka cluster, example: # zookeeper_addrs = "192.168.0.11:2181,192.168.0.12:2181,192.168.0.13:2181" zookeeper_addrs = "" # store slow query log into seperate file enable_slow_query_log = False # enable TLS authentication in the TiDB cluster enable_tls = False # KV mode deploy_without_tidb = False # Optional: Set if you already have a alertmanager server. # Format: alertmanager_host:alertmanager_port alertmanager_target = "" grafana_admin_user = "admin" grafana_admin_password = "admin"
部署任務
-
確認
tidb-ansible/inventory.ini文件中ansible_user = vagrant,本例使用vagrant用戶作為服務運行用戶,配置如下:## Connection # ssh via normal user ansible_user = vagrant執行以下命令如果所有 server 返回 vagrant 表示 ssh 互信配置成功。
ansible -i inventory.ini all -m shell -a 'whoami'執行以下命令如果所有 server 返回 root 表示 vagrant 用戶 sudo 免密碼配置成功。
ansible -i inventory.ini all -m shell -a 'whoami' -b -
執行
local_prepare.ymlplaybook,聯網下載 TiDB binary 到中控機:ansible-playbook local_prepare.yml -
初始化系統環境,修改內核參數
ansible-playbook bootstrap.yml -
部署 TiDB 集群軟件
ansible-playbook deploy.yml -
啟動 TiDB 集群
ansible-playbook start.yml# 返回下列字段時,表示啟動成功 Congrats! All goes well. :-)
測試集群
測試連接 TiDB 集群,推薦在 TiDB 前配置負載均衡來對外統一提供 SQL 接口。
-
使用 MySQL 客戶端連接測試,TCP 4000 端口是 TiDB 服務默認端口。
mysql -u root -h 192.168.12.22 -P 4000# eg vagrant@vagrant [09:48:48 PM] [~/tidb-ansible] [master *] -> % mysql -h192.168.12.22 -uroot -P 4000 Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1 Server version: 5.7.10-TiDB-v2.0.0-rc.4-147-g00d4831 MySQL Community Server (Apache License 2.0) Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> -
通過瀏覽器訪問監控平台。
地址:
http://192.168.12.22:3000默認帳號密碼是:admin/admin
Docker Compose 部署方案
待補充…
數據同步
由於 TiDB 本身兼容絕大多數的 MySQL 語法,所以對於絕大多數業務來說,最安全的切換數據庫方式就是將 TiDB 作為現有數據庫的從庫接在主 MySQL 庫的后方, 這樣對業務方實現完全沒有侵入性下使用 TiDB 對現有的業務進行備份,應對未來數據量或者並發量增長帶來的單點故障風險,如需上線 TiDB, 也只需要簡單的將業務的主 MySQL 地址指向 TiDB 即可。
下面我們詳細介紹了如何將 MySQL 的數據遷移到 TiDB,並將 TiDB 作為 MySQL 的 Slave 進行數據同步。
這里我們假定 MySQL 以及 TiDB 服務信息如下:
+------------------+-----------------+----------------------------------------+
| Name | Address | Port | User | Password | +------------------+-----------------+----------------------------------------+ | MySQL | 127.0.0.1 | 3306 | root | | | TiDB | 192.168.12.22 | 4000 | vagrant | | +------------------+-------------+--------+-----------+-----------------------+
下載 TiDB 企業版工具集 (Linux)
注:普通工具集中,無
syncer,mydumper等工具
# 下載 tool 壓縮包 wget http://download.pingcap.org/tidb-enterprise-tools-latest-linux-amd64.tar.gz wget http://download.pingcap.org/tidb-enterprise-tools-latest-linux-amd64.sha256 # 檢查文件完整性,返回 ok 則正確 sha256sum -c tidb-enterprise-tools-latest-linux-amd64.sha256 # 解開壓縮包 tar -xzf tidb-enterprise-tools-latest-linux-amd64.tar.gz cd tidb-enterprise-tools-latest-linux-amd64
使用 checker 進行 Schema 檢查
在遷移之前,我們可以使用 TiDB 的 checker 工具,checker 是我們開發的一個小工具,用於檢測目標 MySQL 庫中的表的表結構是否支持無縫的遷移到 TiDB, TiDB 支持絕大多數的 MySQL 常用的原生數據類型,所以大多數情況 checker 的返回應該是 ok。如果 check 某個 table schema 失敗,表明 TiDB 當前並不支持, 我們不能對該 table 里面的數據進行遷移。checker 包含在 TiDB 工具集里面。
./bin/checker -host 127.0.0.1 -port 3306 -user root -password password db_name
2016/10/27 13:11:49 checker.go:48: [info] Checking database db_name
2016/10/27 13:11:49 main.go:37: [info] Database DSN: root:@tcp(127.0.0.1:3306)/db_name?charset=utf8
2016/10/27 13:11:49 checker.go:63: [info] Checking table t1
2016/10/27 13:11:49 checker.go:69: [info] Check table t1 succ 2016/10/27 13:11:49 checker.go:63: [info] Checking table t2 2016/10/27 13:11:49 checker.go:69: [info] Check table t2 succ
使用 mydumper/myloader 全量導入數據
我們使用 mydumper 從 MySQL 導出數據,然后用 myloader 將其導入到 TiDB 里面。
注意,雖然我們也支持使用 MySQL 官方的 mysqldump 工具來進行數據的遷移工作,但相比於 mydumper/myloader,性能會慢很多, 對於大量數據的遷移會花費很多時間,這里我們並不推薦。
mydumper/myloader是一個更強大的數據遷移工具,具體可以參考https://github.com/maxbube/mydumper。
# 下載 mydumper 壓縮包 wget http://download.pingcap.org/mydumper-linux-amd64.tar.gz wget http://download.pingcap.org/mydumper-linux-amd64.sha256 # 檢查文件完整性,返回 ok 則正確 sha256sum -c mydumper-linux-amd64.sha256
# 解開壓縮包 tar -xzf mydumper-linux-amd64.tar.gz cd mydumper-linux-amd64
從 MySQL 導出數據
我們使用 mydumper 從 MySQL 導出數據,如下:
./bin/mydumper -h 127.0.0.1 -P 3306 -u root -t 16 -F 128 -B test -T t1,t2 -o ./guopisql
上面,我們使用-B test表明是對test這個database操作,然后用-T t1,t2表明只導出t1,t2兩張表。 -t 16表明使用16個線程去導出數據。-F 128是將實際的table切分成多大的chunk,這里就是128MB一個chunk。
注意:在阿里雲一些需要super privilege的雲上面,mydumper需要加上--no-locks參數,否則會提示沒有權限操作。
給 TiDB 導入數據
我們使用 myloader 將之前導出的數據導入到 TiDB。
./bin/myloader -h 192.168.12.22 -P 4000 -u vagrant -p password -t 16 -q 100 -d ./guopisql
這里-q 100表明每個事務包含多少個query,默認是1000,我們這里使用100就可以了(數據多的話,可以加大)。
導入成功之后,我們可以用 MySQL 官方客戶端進入 TiDB,查看:
vagrant@vagrant [09:48:48 PM] [~/tidb-ansible] [master *]
-> % mysql -h192.168.12.22 -uroot -P 4000 mysql> show tables; +----------------+ | Tables_in_test | +----------------+ | t1 | | t2 | +----------------+
使用 syncer 增量導入數據實現數據和 MySQL 實時同步
上面我們介紹了如何使用mydumper/myloader將 MySQL 的數據全量導入到 TiDB,但如果后續 MySQL 的數據有更新,我們仍然希望快速導入, 使用全量的方式就不合適了。
TiDB 提供syncer工具能方便的將 MySQL 的數據增量的導入到 TiDB 里面。
syncer也屬於 TiDB 企業工具集。
假設我們之前已經使用mydumper/myloader導入了t1和t2兩張表的一些數據,現在我們希望這兩張表的任何更新, 都是實時的同步到 TiDB 上面。
MySQL 開啟 binlog
在使用 syncer 之前,我們必須保證:
- MySQL 開啟 binlog 功能,參考Setting the Replication Master Configuration
- Binlog 格式必須使用
row format,這也是 MySQL 5.7 之后推薦的binlog格式
# sudo vi /etc/mysql/my.cnf [mysqld] log-bin=mysql-bin server-id=1 binlog-format=ROW
重啟mysql服務
sudo service mysql restart
獲取同步 position
我們通過show master status得到當前binlog的position,syncer的初始同步位置就是從這個地方開始。
show master status; +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000001 | 154 | | | | +------------------+----------+--------------+------------------+-------------------+
我們將position相關的信息保存到一個syncer.meta文件里面,用於syncer的同步:
# vim syncer.meta binlog-name = "mysql-bin.000001" binlog-pos = 154
啟動 syncer
syncer的配置文件config.toml:
log-level = "info" server-id = 1 # meta 文件地址 meta = "./syncer.meta" worker-count = 1 batch = 1 pprof-addr = ":10081" [from] host = "127.0.0.1" user = "root" password = "your password" port = 3306 [to] host = "192.168.12.22" user = "root" password = "" port = 4000
啟動syncer
# 后台運行 vagrant@vagrant [10:10:07 PM] [~/tidb-enterprise-tools-latest-linux-amd64] -> % nohup ./bin/syncer -config config.toml & [1] 4193
syncer每隔30s會輸出當前的同步統計,如下:
# cat nohub.out 2018/05/08 15:04:25 syncer.go:821: [info] [syncer]total events = 2, total tps = 0, recent tps = 0, master-binlog = (mysql-bin.000001, 574), master-binlog-gtid=, syncer-binlog = (mysql-bin.000001, 574), syncer-binlog-gtid = 2018/05/08 15:04:55 syncer.go:821: [info] [syncer]total events = 2, total tps = 0, recent tps = 0, master-binlog = (mysql-bin.000001, 574), master-binlog-gtid=, syncer-binlog = (mysql-bin.000001, 574), syncer-binlog-gtid = 2018/05/08 15:05:25 syncer.go:821: [info] [syncer]total events = 2, total tps = 0, recent tps = 0, master-binlog = (mysql-bin.000001, 574), master-binlog-gtid=, syncer-binlog = (mysql-bin.000001, 574), syncer-binlog-gtid = 2018/05/08 15:05:55 syncer.go:821: [info] [syncer]total events = 2, total tps = 0, recent tps = 0, master-binlog = (mysql-bin.000001, 574), master-binlog-gtid=, syncer-binlog = (mysql-bin.000001, 574), syncer-binlog-gtid =
在 MySQL 插入新的數據
INSERT INTO t1 VALUES (4, 4), (5, 5);
登錄到 TiDB 查看:
mysql -h127.0.0.1 -P4000 -uroot -p mysql> select * from t1; +----+------+ | id | age | +----+------+ | 1 | 1 | | 2 | 2 | | 3 | 3 | | 4 | 4 | | 5 | 5 | +----+------+
