官术网_书友最值得收藏!

4.4 容器云上的數(shù)據(jù)庫定制化方案

在本節(jié)中,我們將介紹MySQL在容器云上的定制化。下面先簡單了解一下分布式數(shù)據(jù)庫的發(fā)展。

4.4.1 分布式數(shù)據(jù)庫的發(fā)展

數(shù)據(jù)庫大致經(jīng)歷了三個發(fā)展階段:RDBMS(2008年以前)→NoSQL(2008—2013年)→NewSQL(2013年以后)。

2008年的數(shù)據(jù)庫的數(shù)量級都是GB級別。RDBMS解決了很多復(fù)雜的問題,如join操作、主外鍵等。隨著互聯(lián)網(wǎng)高速發(fā)展,數(shù)據(jù)量增長速度加快,RDBMS無法線性擴(kuò)展,NoSQL應(yīng)運而生。

NoSQL的全稱是Not Only SQL。它的優(yōu)勢包括海量擴(kuò)展能力、讀寫高性能,并且可以與關(guān)系型數(shù)據(jù)庫相輔相成。

NoSQL有以下幾類產(chǎn)品。

  • 鍵值(KV)存儲型數(shù)據(jù)庫:Memcached、Redis。
  • 列存儲型數(shù)據(jù)庫:Cassadra、HBase。
  • 圖形數(shù)據(jù)庫(Graph):Neo4J、InfoGrid、Infinite Graph。
  • 文檔型數(shù)據(jù)庫:MongoDB、CouchDB。

MongoDB被大量應(yīng)用在容器上,其典型應(yīng)用場景如下。

  • 基于位置的移動搜索應(yīng)用(基于自身地理空間索引)。
  • 日志分析平臺(MongoDB自帶高性能的聚合框架)。
  • 可以存儲簡歷或投遞關(guān)系等相對復(fù)雜的數(shù)據(jù)結(jié)果,如簡歷庫。
  • 存儲用戶數(shù)據(jù)、帖子信息。

NewSQL同時滿足NoSQL以及在線交易事務(wù),是分布式數(shù)據(jù)庫的發(fā)展方向。簡單而言:NewSQL=RDBMS(ACID)+SQL+NoSQL(擴(kuò)展性)。

NewSQL的主要目的是替換傳統(tǒng)數(shù)據(jù)庫的分庫分表,解決如MySQL+MongoDB的大數(shù)據(jù)性能瓶頸、業(yè)務(wù)層邏輯復(fù)雜度的增加(多維度映射)、運維成本高(MySQL 5.5不支持Online DDL操作)、故障切換時間長(30s至1min)、MHA/MMM二次開發(fā)等問題。

NewSQL目前有以下幾種。

  • Google的Spanner/F1,不開源。
  • TiDB。
  • CockroachDB:百度在用。
  • OceanBase。
  • 華為的GaussDB。
  • 騰訊的TDSQL。

在以上幾種NewSQL數(shù)據(jù)庫中,TiDB被廣泛使用,尤其是在容器云上。TiDB已經(jīng)針對OpenShift發(fā)布了TiDB Operator。需要注意的是,TiDB無法直接參與到分布式事務(wù)中,它只是在寫數(shù)據(jù)的時候可以強一致地寫到多個節(jié)點中,即它是按照處理本地事務(wù)的方式實現(xiàn)分布式寫數(shù)據(jù)。TiDB不支持MySQL的存儲過程、觸發(fā)器等。TiDB高度兼容MySQL協(xié)議,支持基于Raft算法的多副本復(fù)制。

4.4.2 MySQL的復(fù)制與高可用

MySQL是一個輕量級數(shù)據(jù)庫,在容器云上部署時,有的客戶會選擇購買第三方服務(wù)商的MySQL容器化服務(wù)和產(chǎn)品,有的客戶會自行構(gòu)建基于容器云的MySQL集群。

要實現(xiàn)MySQL上容器云,需要關(guān)注MySQL兩方面的技術(shù)。

  • 復(fù)制技術(shù):主從復(fù)制、半同步復(fù)制、組復(fù)制。
  • 高可用技術(shù):MHA、MGR、MySQL InnoDB Cluster。

需要指出的是,MySQL的高可用技術(shù)依賴于MySQL的復(fù)制技術(shù)。下面介紹常用的MySQL的復(fù)制技術(shù)以及高可用技術(shù)。

MySQL有多種復(fù)制技術(shù),廣為使用的復(fù)制技術(shù)主要有以下三種。

  • 主從復(fù)制:在這種模式中,主從實例的復(fù)制是異步復(fù)制,主實例可讀寫,從實例可讀。從庫通過I/O線程連接主庫,獲取主庫二進(jìn)制日志寫到本地中繼日志,并更新master-info文件(存放主庫相關(guān)信息),再利用SQL線程執(zhí)行中繼日志。
  • 半同步復(fù)制是在第一種主從復(fù)制的基礎(chǔ)上,利用插件完成半同步復(fù)制。對于傳統(tǒng)的主從復(fù)制,不管從庫是否正確獲取到二進(jìn)制日志,主庫都會不斷更新。而對于半同步復(fù)制,只有當(dāng)確認(rèn)了從庫把二進(jìn)制日志寫入中繼日志才會允許提交更新,如果從庫遲遲不返回ACK確認(rèn)信息,則主庫會自動將半同步復(fù)制狀態(tài)取消,進(jìn)入最基本的主從復(fù)制模式。
  • 組復(fù)制(MySQL Group Replication,MGR)。MGR是MySQL官方在5.7.17版本引進(jìn)的一個數(shù)據(jù)庫高可用與高擴(kuò)展的解決方案,并于2016年12月正式推出。MGR 在原生復(fù)制技術(shù)之上引入分布式強一致性協(xié)議——Paxos,以插件的方式提供。MySQL官方還基于MGR推出了MySQL InnoDB Cluster,為MySQL提供完整的高可用性解決方案。

常見的幾種MySQL高可用技術(shù)介紹如下。

  • MHA(Master High Availability),目前在MySQL高可用方面是一個相對成熟的解決方案,也是一套優(yōu)秀的MySQL高可用性環(huán)境下故障切換和主從提升的高可用軟件。MHA依賴于MySQL的主從復(fù)制技術(shù)。
  • 基于MGR實現(xiàn)的高可用。但這種方案的缺點是外部獲得狀態(tài)變更時需要讀取數(shù)據(jù)庫,且外部需要使用LVS、VIP配置。
  • MySQL InnoDB Cluster。這是目前MySQL最完整的高可用解決方案,它依賴于MGR復(fù)制技術(shù)。需要注意的是,當(dāng)前直接在OpenShift上實現(xiàn)MySQL InnoDB Cluster的難度還是比較大的。

接下來,我們介紹如何在OpenShift部署純開源、原生的MySQL,以及MySQL容器鏡像的部署方式,以期對想了解在容器云上部署原生MySQL的讀者有一些幫助。

4.4.3 OpenShift提供的MySQL容器鏡像

紅帽O(jiān)penShift提供了MySQL的容器鏡像,最新的版本是MySQL 8.0(截至2021年9月)。如圖4-78所示,第一個鏡像是基于RHEL7實現(xiàn),第二個鏡像是基于RHEL8實現(xiàn)。

136-1

圖4-78 紅帽O(jiān)penShift提供的MySQL容器鏡像

我們查看第一個rhel8/mysql-80鏡像的配置文件的部分內(nèi)容,如下所示:

FROM ubi8/s2i-core:rhel8.2
ENV MYSQL_VERSION=8.0 \
    APP_DATA=/opt/app-root/src \
    HOME=/var/lib/mysql
RUN yum -y module enable mysql:$MYSQL_VERSION && \
    INSTALL_PKGS="policycoreutils rsync tar gettext hostname bind-utils groff-base
    mysql-server" && \
    yum install -y --setopt=tsflags=nodocs $INSTALL_PKGS && \
    rpm -V $INSTALL_PKGS && \
    yum -y clean all --enablerepo='*' && \
    mkdir -p /var/lib/mysql/data && chown -R mysql.0 /var/lib/mysql && \
test "$(id mysql)" = "uid=27(mysql) gid=27(mysql) groups=27(mysql)"
COPY 8.0/root-common /
COPY 8.0/s2i-common/bin/ $STI_SCRIPTS_PATH
COPY 8.0/root /

從上面內(nèi)容我們可以看出,該鏡像是基于紅帽RHEL8.2的UBI實現(xiàn),并且具備S2I的能力。

接著查看容器鏡像的Package List,如圖4-79所示,可以看到MySQL的版本是8.0.17。

137-1

圖4-79 rhel8/mysql-80的Package List

在介紹了OpenShift提供的MySQL容器鏡像后,接下來我們介紹在OpenShift上部署MySQL的4種方式:

  • 以命令行方式部署MySQL;
  • 以模板方式部署MySQL;
  • 使用S2I方式定制化部署MySQL;
  • 使用模板部署MySQL主從復(fù)制。

4.4.4 以命令行和模板方式部署MySQL

部署MySQL最簡單的方式是使用podman命令行直接部署(這里我們使用基于RHEL7的mysql8鏡像進(jìn)行驗證):

#podman run -d --nam mysql_database -e MYSQL_USER=user -e MYSQL_PASSWORD=pass -e
    MYSQL_DATABASE=db -p 3306:3306 rhscl/mysql-80-rhel7

查看運行的MySQL的容器鏡像,結(jié)果如圖4-80所示。

137-2

圖4-80 使用命令行直接部署MySQL

但是,在實際生產(chǎn)中直接使用podman命令行運行MySQL容器鏡像顯然是不合適的。此時,我們可以通過模板方式在OpenShift上部署MySQL。在OpenShift中查看MySQL模板,如圖4-81所示。

138-1

圖4-81 使用模板方式部署MySQL

該模板的yaml文件的地址為https://github.com/openshift/origin/blob/master/examples/db-templates/mysql-persistent-template.json,感興趣的讀者可以自行查閱更多內(nèi)容。

使用模板傳遞參數(shù),如圖4-82所示。

138-2

圖4-82 通過模板傳遞參數(shù)

通過模板創(chuàng)建成功后,可以查看Pod的相關(guān)信息:

# oc get pods |grep -i mysql1
mysql1-1-4mkc4                         1/1     Running            0          37m

登錄MySQL Pod查看數(shù)據(jù)庫:

#oc rsh mysql1-1-4mkc4
sh-4.2$  mysql -u root

結(jié)果如圖4-83所示。

139-1

圖4-83 查看數(shù)據(jù)庫

通過模板方式部署MySQL很方便,可以傳遞參數(shù),但這種方式無法實現(xiàn)定制化部署。接下來,我們介紹如何使用S2I方式在OpenShift中定制化部署MySQL。

4.4.5 使用S2I方式定制化部署MySQL

接下來,我們展示如何使用S2I構(gòu)建鏡像的方式實現(xiàn)定制化部署MySQL。該鏡像就是本文開頭展示的mysql8.0容器鏡像。在部署時,我們指定源碼地址為https://github.com/sclorg/mysql-container.git

首先導(dǎo)入紅帽MySQL容器鏡像的ImageStream,以便后續(xù)使用。

#oc import-image rhscl/mysql-80-rhel7 --from=registry.access.redhat.com/rhscl/
     mysql-80-rhel7 --confirm –all -n openshift

ImageStream導(dǎo)入成功,如圖4-84所示。

139-2

圖4-84 ImageStream導(dǎo)入成功

查看openshift項目中的MySQL ImageStream:

# oc get is -n openshift
NAME    MAGE REPOSITORY   TAGS                                          UPDATED
mysql-80-rhel7 8.0,8.0-13,8.0-14,8.0-15,8.0-18,8.0-20 + 16 more... About a minute ago

接下來,利用Imagestream,使用S2I方式定制化部署MySQL容器鏡像:

 oc new-app mysql-80-rhel7:8.0-15~https://github.com/sclorg/mysql-container.git \
--name my-mysql-rhel7 \
--context-dir=examples/extend-image \
--env MYSQL_OPERATIONS_USER=opuser \
--env MYSQL_OPERATIONS_PASSWORD=oppass \
--env MYSQL_DATABASE=opdb \
--env MYSQL_USER=user \
--env MYSQL_PASSWORD=pass

查看上面的輸入?yún)?shù)--context-dir,將examples/extend-image目錄對應(yīng)的內(nèi)容注入。接下來,我們分析這個目錄中包含的腳本。

查看GitHub上源碼examples/extend-image中包含的四個子目錄,如圖4-85所示。

140-1

圖4-85 查看examples/extend-image子目錄

接下來,我們分析四個子目錄的內(nèi)容。

1)mysql-cfg目錄下包含myconfig.cnf腳本文件,該腳本的內(nèi)容如下:

[mysqld]  stored_program_cache = 524288

啟動MySQL容器時,myconfig.cnf將作為mysqld守護(hù)程序的配置注入。

2)mysql-pre-init目錄中包含兩個Shell腳本,80-add-arbitrary-users.sh和90-init-db.sh,二者是在啟動mysqld守護(hù)程序之前執(zhí)行的。腳本中使用了如下變量。

  • $ {mysql_flags}變量,在腳本連接到本地運行的守護(hù)程序時使用。
  • $ MYSQL_RUNNING_AS_MASTER變量,在使用run-mysqld-master命令運行容器時定義。
  • $ MYSQL_RUNNING_AS_SLAVE變量,在使用run-mysqld-slave命令運行容器時定義。

80-add-arbitrary-users.sh的內(nèi)容如下,該腳本用于創(chuàng)建MySQL用戶:

create_arbitrary_users() {
    # Do not care what option is compulsory here, just create what is specified
    log_info "Creating user specified by MYSQL_OPERATIONS_USER (${MYSQL_OPERATIONS_USER}) ..."
    mysql $mysql_flags <<EOSQL
    CREATE USER '${MYSQL_OPERATIONS_USER}'@'%' IDENTIFIED BY '${MYSQL_OPERATIONS_PASSWORD}';
   EOSQL
    log_info "Granting privileges to user ${MYSQL_OPERATIONS_USER} for ${MYSQL_DATABASE} ..."
   mysql $mysql_flags <<EOSQL
    GRANT ALL ON \`${MYSQL_DATABASE}\`.* TO '${MYSQL_OPERATIONS_USER}'@'%' ;
    FLUSH PRIVILEGES ;
    EOSQL
    }
    if ! [ -v MYSQL_RUNNING_AS_SLAVE ]; then
    create_arbitrary_users
fi

90-init-db.sh的內(nèi)容如下所示,該腳本調(diào)用mysql-data/init.sql腳本創(chuàng)建數(shù)據(jù)庫。

init_arbitrary_database() {
    local thisdir
    local init_data_file
    thisdir=$(dirname ${BASH_SOURCE[0]})
    init_data_file=$(readlink -f ${thisdir}/../mysql-data/init.sql)
    log_info "Initializing the arbitrary database from file ${init_data_file}..."
    mysql $mysql_flags ${MYSQL_DATABASE} < ${init_data_file}
    }
    if ! [ -v MYSQL_RUNNING_AS_SLAVE ] && $MYSQL_DATADIR_FIRST_INIT ; then
    init_arbitrary_database
fi

3)mysql-data目錄中包含init.sql腳本文件,該腳本用于創(chuàng)建數(shù)據(jù)庫表的SQL語句。如下代碼所示,創(chuàng)建名為products的數(shù)據(jù)庫表,并注入數(shù)據(jù),該腳本被90-init-db.sh腳本調(diào)用。

CREATE TABLE products (id INTEGER, name VARCHAR(256), price FLOAT, variant INTEGER);
CREATE TABLE products_variant (id INTEGER, name VARCHAR(256));
INSERT INTO products_variant (id, name) VALUES ('1', 'blue'), ('2', 'green');

4)mysql-pre-init目錄中包含80-check-arbitrary-users.sh腳本文件,該腳本用于判斷部署MySQL時是否指定參數(shù),如果不指定,則會提示報錯。

check_arbitrary_users() {
  if ! [[ -v MYSQL_OPERATIONS_USER && -v MYSQL_OPERATIONS_PASSWORD && -v MYSQL_
    DATABASE ]]; then
    echo "You need to specify all these variables: MYSQL_OPERATIONS_USER, MYSQL_
      OPERATIONS_PASSWORD, and MYSQL_DATABASE"
    return 1
  fi
}

if ! [ -v MYSQL_RUNNING_AS_SLAVE ]; then
  check_arbitrary_users

我們查看部署結(jié)果,看到MySQL Pod部署成功:

# oc get pods
NAME                      READY   STATUS      RESTARTS   AGE
my-mysql-rhel7-1-4v9dk    1/1     Running     0          9m24s
my-mysql-rhel7-1-build    0/1     Completed   0          10m
my-mysql-rhel7-1-deploy   0/1     Completed   0          9m28s

查看Pod部署的部分日志,我們看到在S2I源碼倉庫定義的腳本被執(zhí)行:

=> sourcing 20-validate-variables.sh ...
=> sourcing 25-validate-replication-variables.sh ...
=> sourcing 30-base-config.sh ...
---> 01:39:10  Processing basic MySQL configuration files ...
=> sourcing 60-replication-config.sh ...
=> sourcing 70-s2i-config.sh ...
---> 01:39:10  Processing additional arbitrary  MySQL configuration provided by s2i ...
=> sourcing 40-paas.cnf ...
=> sourcing 50-my-tuning.cnf ...
=> sourcing myconfig.cnf ...
=> sourcing 80-check-arbitrary-users.sh ...
---> 01:39:10  Initializing database ...
---> 01:39:10  Running /opt/rh/rh-mysql80/root/usr/libexec/mysqld --initialize   --datadir=/var/lib/mysql/data
---> 01:39:17  Starting MySQL server with disabled networking ...
---> 01:39:17  Waiting for MySQL to start ...
2020-05-15T01:39:17.779572Z 0 [Warning] [MY-011070] [Server] 'Disabling symbolic
    links using --skip-symbolic-links (or equivalent) is the default. Consider not
    using this option as it' is deprecated and will be removed in a future release.
2020-05-15T01:39:17.782325Z 0 [System] [MY-010116] [Server] /opt/rh/rh-mysql80/
    root/usr/libexec/mysqld (mysqld 8.0.13) starting as process 86


=> sourcing 40-datadir-action.sh ...
---> 01:39:40     Running datadir action: upgrade-warn
---> 01:39:40     MySQL server version check passed, both server and data
    directory are version 8.0.
=> sourcing 50-passwd-change.sh ...
---> 01:39:40     Setting passwords ...


=> sourcing 80-add-arbitrary-users.sh ...
---> 01:39:41     Creating user specified by MYSQL_OPERATIONS_USER (opuser) ...
---> 01:39:41     Granting privileges to user opuser for opdb ...


=> sourcing 90-init-db.sh ...
---> 01:39:41     Initializing the arbitrary database from file /opt/app-root/src/
    mysql-data/init.sql...
---> 01:39:41     Shutting down MySQL ...

部署成功后,連接部署的數(shù)據(jù)庫,驗證S2I注入的數(shù)據(jù)庫腳本是否執(zhí)行成功:

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| opdb               |
| performance_schema |
| sys                |

mysql> use opdb;
Database changed

我們看到數(shù)據(jù)庫表products被自動創(chuàng)建:

mysql> show tables;
+------------------+
| Tables_in_opdb   |
+------------------+
| products         |
| products_variant |
+------------------+
2 rows in set (0.02 sec)


mysql> select * from products_variant;
+------+-------+
| id   | name  |
+------+-------+
|    1 | blue  |
|    2 | green |
+------+-------+
2 rows in set (0.00 sec)

從上述執(zhí)行結(jié)果可以看出,在部署MySQL時,S2I注入的腳本被執(zhí)行。

通過使用S2I方式,我們可以實現(xiàn)MySQL的定制化部署,甚至可以把MySQL的復(fù)制配置、數(shù)據(jù)庫數(shù)據(jù)導(dǎo)入的腳本放進(jìn)去。

4.4.6 使用模板部署MySQL主從復(fù)制

MySQL主從復(fù)制可以使用模板進(jìn)行部署。GitHub上有一主一從復(fù)制的模板(https://github.com/davidsajare/FSI-IT-construction/blob/main/Chapter4/mysql_replica.json),我們可以基于這個模板進(jìn)行定制化。需要注意的是,目前這個模板只能在一個OpenShift集群內(nèi)部署MySQL主從復(fù)制,而不能跨OpenShift集群部署主從復(fù)制。

在OpenShift中借鑒該模板部署MySQL主從復(fù)制,首先創(chuàng)建MySQL模板:

#oc apply -f mysql_replica.json -n openshift
template.template.openshift.io/mysql-replication-example created

# oc get template
NAME                        DESCRIPTION                 PARAMETERS        OBJECTS
mysql-replication-example   MySQL Replication Example   8 (3 generated)   6

在OpenShift UI界面,選擇創(chuàng)建好的模板,如圖4-86所示。

143-1

圖4-86 選擇創(chuàng)建好的模板

傳遞部署MySQL的參數(shù),如圖4-87所示。

144-1

圖4-87 使用MySQL模板傳遞參數(shù)

Pod部署成功的效果如下所示:

# oc get pods
NAME                READY   STATUS      RESTARTS   AGE
mysql-master-1-deploy   0/1     Completed   0          8m16s
mysql-master-1-fdb9l    1/1     Running     5          8m13s
mysql-slave-1-deploy    0/1     Completed   0          8m16s
mysql-slave-1-zqjc5     1/1     Running     5          8m12s

分別查看Primary和Replica pod的日志,可以看出主從復(fù)制關(guān)系已經(jīng)建立。

Primary pod:
# oc logs -f mysql-master-1-fdb9l
2020-05-15T06:01:28.281730Z 0 [Note] /opt/rh/rh-mysql57/root/usr/libexec/mysqld:
    ready for connections.
Version: '5.7.24-log'  socket: '/var/lib/mysql/mysql.sock'  port: 3306
    MySQL Community Server (GPL)
2020-05-15T06:01:35.879641Z 3 [Note] Start binlog_dump to master_thread_id(3)
    slave_server(3672989091), pos(, 4)

Replica pod:
# oc logs -f mysql-slave-1-zqjc5mysql-slave-1-zqjc5
2020-05-15T06:01:35.875170Z 2 [Note] Slave I/O thread for channel '': connected to
    master 'master@mysql-master:3306',replication started in log 'FIRST' at position 4

查看MySQL的Binlog狀態(tài),顯示正常,如圖4-88所示。

144-2

圖4-88 查看MySQL Binlog狀態(tài)

至此,我們完成了MySQL主從復(fù)制在OpenShift上的部署。如果想實現(xiàn)更為復(fù)雜的部署方式,可以基于本節(jié)的模板進(jìn)行修改。

4.4.7 MySQL主從復(fù)制的限制與不足

如前文所述,由于MySQL主從復(fù)制比較容易實現(xiàn),因此被廣泛應(yīng)用于企業(yè)中。但需要注意的是,主從復(fù)制是異步復(fù)制,存在丟數(shù)據(jù)的可能,而數(shù)據(jù)滯后取決于網(wǎng)絡(luò)速度。如果數(shù)據(jù)不一致,就需要手動修復(fù),前提是主庫的Binlog要備份或放置到持久化存儲里,以避免數(shù)據(jù)丟失。

MySQL主從復(fù)制可能出現(xiàn)以下幾種數(shù)據(jù)不一致的情況。

1)從庫出現(xiàn)問題:例如從庫所在容器云的集群出現(xiàn)硬件故障。

2)主庫出現(xiàn)問題:例如主庫所在容器云的集群出現(xiàn)硬件故障。

3)主從庫之間的復(fù)制出現(xiàn)問題:由于網(wǎng)絡(luò)延遲,造成主庫的Binlog沒有及時復(fù)制到從庫中。

針對第一種情況,直接重新創(chuàng)建從庫,與主庫建立新的主從關(guān)系即可。

針對第二種情況,首先中斷復(fù)制關(guān)系,將從庫提升為主庫接受業(yè)務(wù)請求,將Binlog復(fù)制到新的主庫,等到兩個庫數(shù)據(jù)一致時,再恢復(fù)主從關(guān)系。

針對第三種情況,首先查看主庫和從庫的狀態(tài),如果從庫的狀態(tài)是No,說明當(dāng)前從庫未同步,要是主從庫數(shù)據(jù)相差不大,開啟命令同步數(shù)據(jù)就可以了。如果數(shù)據(jù)相差較大,就需要手工復(fù)制Binglog,手工同步數(shù)據(jù)。

針對MySQL跨容器云的方案,比較好的做法是做讀寫分離,這樣不僅可以提升性能,還可以降低主從庫之間數(shù)據(jù)同步的壓力。即主庫做讀寫、從庫做只讀。為了提升性能,我們可以采用一主多從的方案。那么當(dāng)Master掛了以后,選擇哪個Slave提升為主庫?可以根據(jù)哪個從庫上同步的數(shù)據(jù)多,就將其提升為主庫,如圖4-89所示。

145-1

圖4-89 MySQL的主從切換

4.4.8 CDC方案的選擇

在容器云中的MySQL主從復(fù)制通常不能跨容器云實現(xiàn)。所以在更為復(fù)雜的跨數(shù)據(jù)中心場景中,我們可以考慮使用CDC(Change Data Capture,變化數(shù)據(jù)捕獲)方案。即獲取MySQL的變化,然后將這些信息導(dǎo)入消息中間件中,從而使另外一個數(shù)據(jù)中心的業(yè)務(wù)消費端可以消費這些數(shù)據(jù)。

目前開源社區(qū)提供了以下幾種CDC方案,各方案對比如表4-6所示。

表4-6 開源社區(qū)幾種CDC的方案對比

146-1

綜合對比下,我們推薦使用Debezium方案。Debezium是一個由紅帽贊助的開源項目,它為CDC提供了一個低延遲的流式處理平臺。我們可以安裝并且配置Debezium去監(jiān)控數(shù)據(jù)庫,從而使應(yīng)用可以消費對數(shù)據(jù)庫的每一個行級別(row-level)的更改。在這種工作模式下,只有已提交的更改才是可見的,所以我們不用擔(dān)心事務(wù)(transaction)或者更改被回滾(roll back)。

Debezium為所有的數(shù)據(jù)庫更改事件提供了一個統(tǒng)一的模型,所以應(yīng)用不用擔(dān)心每一種數(shù)據(jù)庫管理系統(tǒng)的錯綜復(fù)雜性。另外,由于Debezium用持久化的、有副本備份的日志來記錄數(shù)據(jù)庫數(shù)據(jù)變化歷史,因此,應(yīng)用可以隨時停止再重啟,而不會錯過它停止運行時發(fā)生的事件,保證了所有事件都能被正確、完全地處理掉。

監(jiān)控數(shù)據(jù)庫,并在數(shù)據(jù)變化的時候獲得通知一直是很復(fù)雜的事情。雖然關(guān)系型數(shù)據(jù)庫的觸發(fā)器可以做到,但是它只對特定的數(shù)據(jù)庫有效,而且通常只能更新數(shù)據(jù)庫內(nèi)的狀態(tài)(無法和外部的進(jìn)程通信)。一些數(shù)據(jù)庫雖然提供了監(jiān)控數(shù)據(jù)變化的API或者框架,但是暫沒有形成一個統(tǒng)一的標(biāo)準(zhǔn),每種數(shù)據(jù)庫的實現(xiàn)方式都是不同的,我們需要掌握大量特定的知識和理解特定的代碼才能很好地運用。所以,確保以相同的順序查看和處理所有更改,同時最小化影響數(shù)據(jù)庫仍然非常具有挑戰(zhàn)性。

Debezium利用Kafka和Kafka Connector實現(xiàn)了自己的持久性、可靠性和容錯性。每一個部署在Kafka Connector的分布式、可擴(kuò)展、容錯性服務(wù)中的Connector負(fù)責(zé)監(jiān)控一個上游數(shù)據(jù)庫服務(wù)器,捕獲所有的數(shù)據(jù)庫更改,然后記錄到一個或者多個Kafka Topic(通常一個數(shù)據(jù)庫表對應(yīng)一個Kafka Topic)中。Kafka可以確保所有這些數(shù)據(jù)更改事件都能夠多副本并且總體上有序(Kafka只能保證一個Topic的單個分區(qū)內(nèi)有序),這樣,更多的客戶端就可以獨立消費同樣的數(shù)據(jù)更改事件,并將對上游數(shù)據(jù)庫系統(tǒng)造成的影響降到很低(如果N個應(yīng)用都直接去監(jiān)控數(shù)據(jù)庫更改,則對數(shù)據(jù)庫的壓力為N,而用Debezium匯報數(shù)據(jù)庫更改事件到Kafka,所有的應(yīng)用都去消費Kafka中的消息,可以將對數(shù)據(jù)庫的壓力降到1)。另外,客戶端可以隨時停止消費,然后重啟,從上次停止消費的地方繼續(xù)消費。每個客戶端可以自行決定它們是否需要exactly-once(嚴(yán)格一次)或者at-least-once(最少一次)消息交付語義保證,并且所有的數(shù)據(jù)庫或者表的更改事件是按照上游數(shù)據(jù)庫發(fā)生的順序被交付的。

如果不需要這種容錯級別、性能、可擴(kuò)展性、可靠性的應(yīng)用,也可以使用內(nèi)嵌的Debezium Connector引擎直接在應(yīng)用內(nèi)部運行Connector。雖然這種應(yīng)用仍需要消費數(shù)據(jù)庫更改事件,但我們更希望將Connector直接傳遞給它,而不是持久化到Kafka里。

Debezium支持的數(shù)據(jù)庫有MySQL、PostgreSQL、MongoDB、Microsoft SQL Server、Oracle、Apache Cassandra。

Debezium依賴于Kafaka。通過Debezium可以捕獲容器化MySQL的變化數(shù)據(jù),其架構(gòu)圖如圖4-90所示。

147-1

圖4-90 Debezium捕獲MySQL變化數(shù)據(jù)的架構(gòu)圖

目前Debezium支持的插件如圖4-91所示。

147-2

圖4-91 Debezium支持的插件

如果想了解更多Debezium的具體實現(xiàn)效果,請關(guān)注“大魏分享”公眾號中的文章《CDC(變化數(shù)據(jù)捕獲)在Kubernetes上的實現(xiàn)》。

主站蜘蛛池模板: 仙桃市| 太谷县| 荥经县| 公主岭市| 澄江县| 仪陇县| 安福县| 昌都县| 遂平县| 都安| 通江县| 广西| 诸城市| 禹州市| 延长县| 新乐市| 营口市| 横峰县| 连州市| 新竹县| 宿松县| 柘城县| 年辖:市辖区| 淳安县| 齐河县| 微博| 金坛市| 九台市| 时尚| 阿拉善右旗| 高台县| 德州市| 九龙城区| 旅游| 仁化县| 花垣县| 扎赉特旗| 留坝县| 绥化市| 武功县| 积石山|