1. 程式人生 > >沒有宮廷內鬥,資料庫界的延禧攻略

沒有宮廷內鬥,資料庫界的延禧攻略

640?wx_fmt=jpeg

關注↑↑↑我們獲得更多精彩內容!

640?wx_fmt=jpeg

作者 | 張甦, 資料庫領域的專家和知名人士、圖書《MySQL王者晉級之路》作者,51CTO 專家博主。近10年網際網路線上處理及培訓經驗,專注於 MySQL 資料庫,對 MongoDB、Redis 等 NoSQL 資料庫以及 Hadoop 生態圈相關技術有深入研究,具備非常豐富的理論與實戰經驗。

各位老鐵們,你們有沒有想老張,最近老張的才華被工作的繁忙所限制了,所以一直沒時間更博,今兒個時隔數日我們終於再次見面啦(很開心)!最近有部特別火的宮廷戲,不知道大家有沒有看,劇名叫做《延禧攻略》,講述得是一個宮女,一路過關斬將,最後成為皇上最寵愛的令貴妃的故事。

加上我本人巨愛這類題材,所以痴迷得不得了。(好像暴露了自己沒有更博的真正原因哈哈)。宮廷類的劇,都是後宮嬪妃之間的爾虞吾詐,勾心鬥角,有你沒我,有我沒你的殘酷事實。勝者為王,敗者為寇這種思想好像從古代就一直延續到今日。非要分出個勝負,分出個誰好,誰壞才罷休。

在資料庫領域也會有此類問題,老張我混跡開源資料庫圈多年。MySQL 資料庫佔領著開源資料庫的頭把交椅,MongoDB 佔領著 NoSQL 資料庫的第一位。我們來看下資料庫的整體排名情況;

640?wx_fmt=png

兩者都是第一,所有總會拿來比較。也會經常被人問及到諸如此類的問題MongoDB4.0 已經問世了,而且支援事務了,是不是將來可以取代 MySQL了。MySQL 和 MongoDB 哪個資料庫好用啊。今天老張想通過這篇文章,帶著大家全方位解讀 MySQL 與 MongoDB 的區別。讓有困惑的老鐵們明白,沒有誰替代誰,只有哪個場景更適合誰。

我們從下面四個方向依次闡明兩者的區別。只有更瞭解彼此,讓能更好地利用它們的功能性。

640?wx_fmt=png

01

資料庫概述

我們先來了解一下 MySQL 這個資料庫;

640?wx_fmt=png

再來學習一下 MySQL 資料庫的特點;
640?wx_fmt=png

MySQL瞭解完,同理我們來了解 MongoDB 及其特點的介紹;

640?wx_fmt=png

MongoDB 特點介紹:

640?wx_fmt=png

學習完第一部分之後,我們對兩者資料庫都有了一定的認識;接下來去從運維的角度來檢驗兩者的不同;

02

日常運維管理維度

1. 術語和概念的差異

640?wx_fmt=png
640?wx_fmt=png

結論可以看出,關係型資料庫中的表,在 MongoDB 中叫做集合。行在 MongoDB 中叫做文件。所以經常管 MongoDB 叫做文件型資料庫。

2.儲存資料結構的差異

640?wx_fmt=png

在關係型資料庫中設計表,有些資訊需要多表記錄;而在 MongoDB 中,上面的三張表,就變成下面的這一段程式碼就可以實現了。

{_id:"M416",
name:"zhangsu",
phone:[1234,5678],
.....
}

MongoDB 表設計的特點

  1. 資料聚合

  2. 資料巢狀

  3. 陣列結構

3.啟動配置檔案格式差異

MySQL 資料庫的配置叫做 my.cnf,我們來看下它的記錄方式;

[client]
port    = 3306
socket  = /data/mysql/mysql.sock

[mysql]
prompt="\[email protected] \R:\m:\s [\d]> "no-auto-rehash

[mysqld]
user    = mysql
port    = 3306
basedir = /usr/local/mysql
datadir = /data/mysql/
socket  = /data/mysql/mysql.sock
pid-file = db.pid
character-set-server = utf8mb4
skip_name_resolve = 1
open_files_limit    = 65535
back_log = 1024
max_connections = 512
max_connect_errors = 1000000
table_open_cache = 1024
table_definition_cache = 1024
table_open_cache_instances = 64
thread_stack = 512K
external-locking = FALSE
max_allowed_packet = 32M
sort_buffer_size = 4M
join_buffer_size = 4M
thread_cache_size = 768#query_cache_size = 0#query_cache_type = 0interactive_timeout = 600
wait_timeout = 600
tmp_table_size = 32M
max_heap_table_size = 32M
slow_query_log = 1
slow_query_log_file = /data/mysql/slow.log
log-error = /data/mysql/error.log
long_query_time = 0.1
server-id = 3306101
log-bin = /data/mysql/mybinlog
sync_binlog = 1
binlog_cache_size = 4M
max_binlog_cache_size = 1G
max_binlog_size = 1G
expire_logs_days = 7
master_info_repository = TABLE
relay_log_info_repository = TABLE
gtid_mode = on
enforce_gtid_consistency = 1
log_slave_updates=1
binlog_format = row
relay_log_recovery = 1
relay-log-purge = 1
key_buffer_size = 32M
read_buffer_size = 8M
read_rnd_buffer_size = 4M
bulk_insert_buffer_size = 64M#myisam_sort_buffer_size = 128M#myisam_max_sort_file_size = 10G#myisam_repair_threads = 1lock_wait_timeout = 3600
explicit_defaults_for_timestamp = 1
innodb_thread_concurrency = 0
innodb_sync_spin_loops = 100
innodb_spin_wait_delay = 30

secure_file_priv=''

super_read_only=0

transaction_isolation = REPEATABLE-READ#innodb_additional_mem_pool_size = 16Minnodb_buffer_pool_size = 1024M
innodb_buffer_pool_instances = 8
innodb_buffer_pool_load_at_startup = 1
innodb_buffer_pool_dump_at_shutdown = 1
innodb_data_file_path = ibdata1:100M:autoextend
innodb_flush_log_at_trx_commit = 1
innodb_log_buffer_size = 32M
innodb_log_file_size = 2G
innodb_log_files_in_group = 2
innodb_max_undo_log_size = 4G

innodb_io_capacity = 4000
innodb_io_capacity_max = 8000
innodb_flush_neighbors = 0
innodb_write_io_threads = 8
innodb_read_io_threads = 8
innodb_purge_threads = 4
innodb_page_cleaners = 4
innodb_open_files = 65535
innodb_max_dirty_pages_pct = 50
innodb_flush_method = O_DIRECT
innodb_lru_scan_depth = 4000
innodb_checksum_algorithm = crc32#innodb_file_format = Barracuda#innodb_file_format_max = Barracudainnodb_lock_wait_timeout = 10
innodb_rollback_on_timeout = 1
innodb_print_all_deadlocks = 1
innodb_file_per_table = 1
innodb_online_alter_log_max_size = 4G
internal_tmp_disk_storage_engine = InnoDB
innodb_stats_on_metadata = 0

innodb_status_file = 1

[mysqldump]
quick
max_allowed_packet = 32M

MongoDB 配置檔案使用 Yaml 格式

640?wx_fmt=png

4.增刪改查操作的差異

640?wx_fmt=png

5.事務支援的差異

640?wx_fmt=png

但隨著 MongoDB 4.0 的問世,它將支援多文件事務,屆時 MongoDB 將成為唯一能夠同時支援速度,靈活性,JSON 文件模型優勢 和 ACID 資料完整性保證的資料庫。

所謂的多文件事務,可以理解為關係型資料庫的多行事務。在關係型的事務支援中,大家幾乎無一例外支援同一事務內操作的原子性,即要麼全部提交,要麼全部回滾。這個同一事務內可以有多個操作,針對於多個表,或者是同一個表內的多行資料。

總結:隨著事務支援的增加,MongoDB 功能上更接近於關係型資料庫,但是和關係型還是有本質上的區別:MySQL 是基於關係模型的資料庫,對各種資料多變的場景如物聯網或社交化並沒有 MongoDB 支援得好。MongoDB 的 JSON 模型則具有動態靈活,資料庫無須下線就可以進行模式變遷升級,在這種場景下面,選擇 MongoDB 會特別合適。

6.備份上的差異

MySQL 備份方式:
640?wx_fmt=png

MongoDB備份方式:

邏輯備份與恢復

1.mongodump
2.mongorestore
3.mongoexport
4.mongoimport

注:MongoDB 目前為止還沒有像 xtrabackup 這種好用的備份工具。所以一般來說,都是使用邏輯備份方式來進行操作。

從運維角度我們對它們有了更深的認識之後,我們來從叢集架構的維度出發,去探究其更深的不同之處。

03

叢集架構層面

1.叢集架構層面上的差異

我們先從 MySQL 複製的角度入手;然後再介紹 MySQL 高可用叢集架構

MySQL 主從複製原理圖
640?wx_fmt=png

MySQL複製種類總結;

非同步複製:
通常沒說明指的都是非同步,即主庫執行完 Commit 後,在主庫寫入 Binlog 日誌後即可成功返回客戶端,無需等 Binlog 日誌傳送給從庫,一旦主庫宕機,有可能會丟失日誌。

半同步複製:

MySQL5.5 版本之後引入了半同步複製功能,主從伺服器必須同時安裝半同步複製外掛,才能開啟該複製功能。在該功能下,確保從庫接收完主庫傳遞過來的 binlog 內容已經寫入到自己的 relay log 裡面了,才會通知主庫上面的等待執行緒,該操作完畢。如果等待超時,超過 rpl_semi_sync_master_timeout 引數設定的時間,則關閉半同步複製,並自動轉換為非同步複製模式,直到至少有一臺從庫通知主庫已經接收到 binlog 資訊了為止。

多源複製:
所謂多源複製,就是把多臺主庫的資料同步到一臺從庫伺服器上,從庫會建立通往每個主庫的管道。在 MySQL5.7 之前的版本中,只能實現一主一從、一主多從或者多主多從的複製架構,如果想要實現多主一從的複製,只能使用 MariaDB。MySQL 5.7 版本已經可以實現多主一從的複製。

並行複製:
使用 MySQL5.7 的並行複製功能。在 5.6 版本中就有了並行的概念,但其中的並行複製是基於庫級別的,即 slave_parallel_type=database。但在這種模式下,只是基於多庫少表的情況,並不適用於真實的生產環境下。在 MySQL 5.7 版本中,真正實現了基於組提交的並行複製,簡單說就是主庫並行執行 SQL 語句,從庫也可以通過多個 workers 執行緒併發執行 relay log 中主庫提交的事務。想要開啟MySQL5.7的並行複製可以在從庫設定引數slave_parallel_workers>0,並把 5.7 版本中新新增的 slave_parallel_type 引數設定為 LOGICAL_CLOCK。該引數有 DATABASE 和 LOGICAL_CLOCK 兩個值。MySQL5.6 預設是 database。

MySQL高可用叢集架構分類圖;

640?wx_fmt=png 

MHA:

640?wx_fmt=png

MHA 的目的在於維持 MySQL Replication中master 庫的高可用性,其最大特點是可以修復多個 slave 之間的差異日誌,最終使所有 slave 保持資料一致,然後從中選擇一個充當新的 master,並將其他 slave 指向它。當 master 出現故障時,可以通過對比 slave 之間 I/O thread 讀取主庫 binlog 的 position 號,選取最接近的 slave 作為備選主庫(備胎)。其他的從庫可以通過與備選主庫對比生成差異的中繼日誌。在備選主庫上應用從原來 master 儲存的 binlog,同時將備選主庫提升為 master。最後在其他 slave 上應用相應的差異中繼日誌並從新的 master 開始複製。

雙主+keepalived
640?wx_fmt=png
中小型規模的時候,採用這種架構是最省事的。


兩個節點可以採用簡單的一主一從模式,或者雙主模式,並且放置於同一個 VLAN 中,在 master 節點發生故障後,利用 keepalived/heartbeat 的高可用機制實現快速切換到 slave 節點。

PXC叢集:

640?wx_fmt=png

PXC 是基於 Galera 協議的 MySQL 高可用叢集架構。Galera 產品是以 Galera Cluster 方式為 MySQL 提供高可用叢集解決方案的。Galera Cluster 就是集成了Galera外掛的MySQL叢集。Galera replication 是 Codership 提供的 MySQL 資料同步方案,具有高可用性,方便擴充套件,並且可以實現多個 MySQL 節點間的資料同步複製與讀寫,可保障資料庫的服務高可用及資料強一致性。

MGR架構:
640?wx_fmt=png
MySQL官方在5.7.17版本正式推出組複製(MySQL Group Replication,簡稱MGR)。master1,master2,master3,所有成員獨立完成各自的事務。當客戶端先發起一個更新事務,該事務先在本地執行,執行完成之後就要發起對事務的提交操作了。在還沒有真正提交之前需要將產生的複製寫集廣播出去,複製到其他成員。如果衝突檢測成功,組內決定該事務可以提交,其他成員可以應用,否則就回滾。最終,這意味著所有組內成員以相同的順序接收同一組事務。因此組內成員以相同的順序應用相同的修改,保證組內資料強一致性。

接下來介紹 MongoDB 的複製情況;
MongoDB複製集:
640?wx_fmt=png
三副本架構是最基礎的複製集的架構,一主兩備模式。主節點接受外界的讀寫請求,向備節點進行資料同步。當主節點宕掉,會自動切換到備節點,不影響線上業務,防止單點故障。

MongoDB 複製集自動切換
640?wx_fmt=png
副本集的所有成員都可以接受讀取操作。 但是,預設情況下,應用程式將其讀取操作指向 primary。
副本集可以有至多一個 primary 節點,primary 節點宕機後,叢集會觸發選舉以選出新的 primary 節點。
在以下三成員節點副本集架構中,primary 宕機後,觸發了一次選舉,從剩下的兩個 secondary 節點裡,選舉出了一個新的 primary 節點。

MongoDB 複製集讀寫分離設定
640?wx_fmt=png
read preference 決定 MongoDB 客戶端從哪個節點上讀取資料。

預設情況下,應用程式將其讀取操作指向副本集中的 primary 節點。

指定 read preference 選項時要注意:因為使用非同步複製,複製延遲會導致 secondary 上的資料可能不是最新的。

預設情況下,複製集的所有讀請求都發到 Primary,Driver 可通過設定 Read Preference 來將讀請求路由到其他的節點。

primary: 預設規則,所有讀請求發到 Primary
primaryPreferred: Primary 優先,如果 Primary 不可達,請求 Secondary
secondary: 所有的讀請求都發到 secondary
secondaryPreferred:Secondary 優先,當所有 Secondary 不可達時,請求Primary
nearest:讀請求傳送到最近的可達節點上(通過 ping 探測得出最近的節點)

MongoDB 分片架構
640?wx_fmt=png
分片是一種在多臺機器上分配資料的方法。 MongoDB 使用分片架構有助於您去管理非常大數量的資料集和高吞吐量操作的叢集。

大資料量和高吞吐量的業務情況對單臺伺服器來講是具備很大的挑戰性的。例如,高查詢率可能耗盡伺服器的 CPU 容量。工作集大小超過系統記憶體,那麼壓力則會給到磁碟上,這對 IO 來講不是我們所希望看到的。
MongoDB 支援通過分片進行水平縮放。

總結:MySQL的複製種類很多,叢集架構在選擇性上來說也比較多。但橫向擴充套件能力上,沒有MongoDB的分片架構擴充套件能力強。

最後一部分,我們來通過 MySQL 與 MongoDB 的不同應用場景;來對兩種資料庫做一個最後的總結;

04

應用場景角度

正如開篇介紹 MySQL 特點時說的,MySQL 使用得覆蓋率已經接近100%。從大型 BAT,電商平臺,遊戲公司,甚至諸多傳統行業也無不例外都在往 MySQL 資料庫方向靠攏,達到逐漸壟斷的趨勢。對於 MongoDB 的應用也已經×××到各個領域,比如遊戲、物流、電商、內容管理、社交、物聯網、視訊直播等。

1.遊戲領域:遊戲場景,使用 MongoDB 儲存遊戲使用者資訊,使用者的裝備、積分等直接以內嵌文件的形式儲存,方便查詢、更新。

2.物流場景:使用MongoDB儲存訂單資訊,訂單狀態在運送過程中會不斷更新,以MongoDB內嵌陣列的形式來儲存,一次查詢就能將訂單所有的變更讀取出來。

3.社交場景:使用MongoDB儲存使用者資訊,以及使用者發表的朋友圈資訊,通過地理位置索引實現附近的人、地點等功能

4.物聯網場景:使用MongoDB儲存所有接入的智慧裝置資訊,以及裝置彙報的日誌資訊,並對這些資訊進行多維度的分析

對我而言,2009年開始接觸 MySQL,我在2012年接觸的 MongoDB 的第一個版本 2.1,對於這兩個資料庫真是手心手背都是肉。在我孤獨寂寞的時候,都是它們一直陪伴著我,感謝技術給我們帶來的簡單快樂。無論未來發展如何,沒有所謂的誰會替代誰,只是說它們各自都有不同的特點,促使在不同的應用場景下,我們使用誰更合適而已。這裡沒有宮廷內鬥,沒有爾虞我詐,只有那份最簡單地做技術的心,是現實版的延禧攻略!

對老張而言,寫篇文章很簡單,但真得希望可以幫助到那些剛入門或者想深入學習資料庫的同學們。能力有限,水平一般,哪裡有介紹不到的地方,還望大家海涵!

原創:superZS。

投稿:有投稿意向技術人請在公眾號對話方塊留言。

轉載:意向文章下方留言。

更多精彩請關注 “資料和雲” 公眾號 。

招聘專欄

Oracle 售前工程師(廣州、深圳、上海、武漢、北京、石家莊)

Oracle 高階工程師(上海、深圳、北京、成都、昆明、貴州、西寧)

MySQL 技術經理(上海、南京、成都)

MySQL 工程師(上海、杭州)

超高待遇:豐厚的年終獎,五險一金,高額學習基金,團建旅遊,法定節假日,福利假期等。

推薦他人成功入職有好禮(iPhone X)相送 。

投遞簡歷至郵箱:[email protected]

資源下載

關注公眾號:資料和雲(OraNews)回覆關鍵字獲取

2018DTCC , 資料庫大會PPT

2017DTC,2017 DTC 大會 PPT

DBALIFE ,“DBA 的一天”海報

DBA04 ,DBA 手記4 電子書

122ARCH ,Oracle 12.2體系結構圖

2017OOW ,Oracle OpenWorld 資料

PRELECTION ,大講堂講師課程資料

近期文章

640?wx_fmt=jpeg