数据库往往是系统中的性能瓶颈,所以通常在系统设计中会引入各种各样的缓存机制,以避免频繁访问数据库。另外,数据库由于其重要性,高可用要求也是避免不了的,因为一旦数据库挂了基本上整个系统也就不能使用了。
而以上这些常见问题都是单点数据库带来的限制,为了解决这些问题,达到高性能、高可用的目的,我们就需要在系统架构设计中采用数据库集群方案。
既然单点数据库存在性能问题,那么有没有实际数据呢?下面我们就来对单点数据库进行一个性能测试,看看其并发极限大概是多少。我这里使用了一台2核2G的云服务,mysql版本为8.0.18。
mysql自带了一个性能测试工具:mysqlslap,我们可以使用该工具进行测试,具体的测试参数如下:
[root@localhost ~]# mysqlslap -hlocalhost -uroot -pyour_password -P3306 --concurrency=500 --iterations=1 --auto-generate-sql --auto-generate-sql-load-type=mixed --auto-generate-sql-add-autoincrement --engine=innodb --number-of-queries=500
主要参数说明:
参数 | 说明 |
---|---|
--concurrency |
并发数量,即模拟的客户端数量 |
--iterations |
执行多少次该测试 |
--auto-generate-sql |
使用系统自己生成的SQL脚本来测 |
--auto-generate-sql-load-type |
要测试的是读还是写还是两者混合的(取值:read, write, update, mixed) |
--auto-generate-sql-add-autoincrement |
将自增的列添加到自动生成的表中 |
--engine |
要测试的存储引擎 |
--number-of-queries |
每个客户端的访问次数,该数值除以并发数量就是每个客户端的访问次数,在本例中:500 / 500 = 1 |
这里我分别进行了不同量级的测试,在并发500、1000和5000个连接时,数据库还可以正常处理,没有太大问题:
# 500个并发连接
Benchmark
Running for engine innodb
Average number of seconds to run all queries: 0.391 seconds
Minimum number of seconds to run all queries: 0.391 seconds
Maximum number of seconds to run all queries: 0.391 seconds
Number of clients running queries: 500
Average number of queries per client: 1
# 1000个并发连接
Benchmark
Running for engine innodb
Average number of seconds to run all queries: 0.802 seconds
Minimum number of seconds to run all queries: 0.802 seconds
Maximum number of seconds to run all queries: 0.802 seconds
Number of clients running queries: 1000
Average number of queries per client: 1
# 5000个并发连接
Benchmark
Running for engine innodb
Average number of seconds to run all queries: 3.884 seconds
Minimum number of seconds to run all queries: 3.884 seconds
Maximum number of seconds to run all queries: 3.884 seconds
Number of clients running queries: 5000
Average number of queries per client: 1
但在测试1w个并发连接时,数据库就开始报无法连接的错误了:
由该测试案例可知,普通的单节点数据库性能瓶颈大概在1w个并发连接左右。当然这里的测试结果与机器的硬件差异有关,只是提供一个参考。
上一小节介绍了单点数据库存在的问题,以及进行了一个简单的性能测试。为了应对这些问题,我们需要将单点数据库向集群转变。
目前存在许多的数据库集群方案,而这些方案中也没有哪个好那个坏,只有适合的才是好的。本小节则介绍一下主流的方案之一:PXC集群方案,其架构图大致如下:
上图只是PXC集群最基础的架构,所以还有优化的余地。我们都知道mysql的单表数据处理的性能极限在2千万左右,当数据达到这个量级时,mysql的处理性能就会很低下了。而上图中每个PXC节点都会进行数据的同步,所以当每个节点的数据量级都达到2千万时,整个集群的性能就会降低。
这时就需要增加多一个集群,并且这两个集群之间的数据是不进行同步的。为了让不同的集群存储不同的数据,就得引入Mycat这种数据库中间件将数据进行切分,让数据可以在不同的集群上进行读写,分散存储压力。在这个场景下,一个集群称为一个数据分片。如图:
我们知道数据库数据的一致性和持久性是通过事务来保证的,而PXC集群的强一致性也是采用了事务,只不过这个事务是分布式事务。
客户端在写入数据完成后,同样需要提交一个事务,在事务内节点之间会进行数据的同步复制。该事务会作用到集群内的所有节点上,保证所有节点要么全写入成功,要么全写入失败。这里用一个时序图表达一下大致流程:
搭建PXC集群需要注意的事项:
说了那么多,我们还没介绍PXC是个啥玩意呢。PXC是Percona XtraDB Cluster的缩写,PXC是基于mysql自带的Galera集群技术,将不同的mysql实例连接起来,实现的多主集群。在PXC集群中每个mysql节点都是可读可写的,也就是主从概念中的主节点,不存在只读的节点。
PXC可以集群任何mysql的衍生版本,例如MariaDB和Percona Server。由于Percona Server的性能最接近于mysql企业版,性能相对于标准版的mysql有显著的提升,并且对mysql基本兼容。所以在搭建PXC集群时,通常建议基于Percona Server进行搭建。
PXC集群的数据强一致性是以牺牲性能为代价的,因为客户端需要等待所有的节点写入数据。而与之相反的一种集群方案就是本小节要介绍的Replication集群。该方案不牺牲性能,但不具有数据强一致性,正可谓鱼和熊掌不可兼得。
所谓读写非强一致的意思就是在A节点成功写入数据,并提交了事务。但在B节点上进行读取时,可能会读取不到写入的数据。
因为这里提交的事务只是该节点的本地事务,只能保证数据成功写入了该节点,而不保证数据成功写入整个集群内的节点。当该节点与其他节点进行数据同步时,可能会由于种种原因没有成功同步数据,从而导致在其他节点上读不到该数据。
所以该集群方案就不适合保存高价值的数据,但对于非高价值的数据,又对读写性能要求高的,就适合采用该集群方案。例如,用户行为日志、操作日志及商品描述等这类非重要的数据。
同样的,上图只是Replication集群最基础的架构,也需要在数据量达到一定规模时采用Mycat对数据进行分片处理。如图:
实际上,在大型的系统架构中,往往不是单独采用某一种特定的集群方案,而是多种方案进行结合。例如,PXC集群和Replication集群就可以结合使用,让PXC集群存储高价值数据,Replication集群存储低价值数据。然后采用Mycat等数据库中间件来完成集群之间的数据分片及管理,如图:
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。