没有宫廷内斗,数据库界的延禧攻略

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="\u@db \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)相送 。

投递简历至邮箱:hr@enmotech.com

资源下载

关注公众号:数据和云(OraNews)回复关键字获取

2018DTCC , 数据库大会PPT

2017DTC,2017 DTC 大会 PPT

DBALIFE ,“DBA 的一天”海报

DBA04 ,DBA 手记4 电子书

122ARCH ,Oracle 12.2体系结构图

2017OOW ,Oracle OpenWorld 资料

PRELECTION ,大讲堂讲师课程资料

近期文章

仅仅使用AWR做报告? 性能优化还未入门

实战课堂:一则CPU 100%的故障分析

杨廷琨:如何编写高效SQL(含PPT)

一份高达555页的技术PPT会是什么样子?

大象起舞:用PostgreSQL解海盗分金问题

ProxySQL!像C罗一样的强大

高手过招:用SQL解决环环相扣刑侦推理问题

640?wx_fmt=jpeg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值