当前位置: 首页 > 科技观察

数据库的这些性能优化你做过吗?

时间:2023-03-20 17:49:08 科技观察

在互联网项目中,当业务规模变大,数据变大时,数据库的压力也会相应增加。我们可能会采取多种方式进行优化,比如上一篇文章中提到的缓存方案、SQL优化等。除了这些方式之外,这里还有几个比较常规的数据库优化方式:“数据读写分离”和“数据库分片”。这两点基本上是大中型互联网项目中使用的非常普遍的方案。下面我们来详细了解一下。一、从读写分离到CQRS(图片来源阿里云)由于互联网业务场景,大多是读多写少,所以在数据库中进行读写分离是非常简单高效的。方案。简单来说,读写分离就是将数据的读写操作分开,让这两个操作访问不同的数据库。这样可以减轻数据库的压力。比如上图中,数据库会有一个“主实例”,主要用来提供写操作(偶尔也会承担一些读操作)。除了“主实例”之外,还会有多个“从实例”(图中为只读实例),“从实例”的功能只是用来承担读操作。那么上面有多个数据库,如何保证多个数据库之间数据的一致性呢?其实我们常用的数据库都有自己的同步功能,比如Mysql有主从功能可以自动同步主从数据库的数据,它是基于二进制日志复制的。主库中的写操作会形成二进制日志,然后Mysql会异步同步日志到从库,从库会自动再次执行二进制日志,数据就会和主库保持一致。除了Mysql,Oracle等商业数据库也有类似的功能,网上什至还有很多开源的第三方数据同步工具,成熟好用的也不在少数。好了,“主实例”和“从实例”之间的数据同步问题就解决了。现在还有一个问题,如何让项目中的写请求访问“主实例”,读请求访问“从实例”。Instance”,这个路由规则是如何实现的?常规的方法有两种:使用编码方式。这种方式主要靠开发同学在编码时根据读写不同的操作需求调用不同的数据源。比如,在数据操作层(DAO层),读取数据和写入数据分离成两个方法(函数),然后为这两个方法指定不同的数据库。但是这个方法有点硬编码,对于开发者来说,你有这件事要格外注意,有额外的编码成本,很容易不小心忽略掉。中间件的使用方式是在后端数据库前面放一个数据库代理服务,如下图:MySQL-Proxy是Mysql提供的一个中间件,用于实现读写分离请求,但是实际使用这个组件的人并不多,我们可以选择一些其他的开源组件来代替,比如:MyCat、ProxySQL等,但是大体原理是类似的,通过这个也很容易理解这个模式图表。好了,基本的读写分离就讲完了,但是我觉得这种方法虽然实用实用,但是也不是很有说服力。好的,如果你想引人注目,对吧?为了让你满意,那我们再来说说另一个很牛逼的读写分离概念:“CQRS”CQRS:CommandQueryResponsibilitySegregation命令(增删改查)和查询职责分离先看图。从上图我们可以简单的理解CQRSCQRS强调Query(读)和Command(写)的分离,在业务上把职责分得很清楚。Command主要负责业务逻辑的执行,Query负责数据的查询和展示。同时这两种操作是基于不同的数据源,甚至一个是数据库,一个是NoSQL。Query查询的数据源可以直接按照领域模型存储,而不是按照数据模型存储。出来后可以立即显示,无需转换,查询效率高。其实CQRS是由大名鼎鼎的MartinFowler提出的,搞计算机的应该都知道。如果想深入了解CQRS,可以阅读MartinFowler发表的资料。2.分库(分库分表)以上就完成了数据库的读写分离。下面说说数据库的分片。随着数据库中的数据越来越大,单表查询的性能已经不能满足业务需求。这时候就需要把表分成几个小表,不同的子表中的数据也不一样,这样可以分散查询压力,提高处理效率。但是,当表越来越多,所有的数据都在一个数据库上时,网络IO和文件IO也会集中在一个数据库上,可能会超过单台服务器的能力,CPU、内存、文件IO、网络IO会成为系统的瓶颈,QPS/TPS也会超过单个数据库实例的处理极限。那么这个时候就需要对数据库进行分片。因为分表和分库的思路差不多,所以统一说一下技术方案。其实分库分表只是我们通俗易懂的语言。正确的描述应该是:datasharding数据分片主要有两种方式:垂直拆分和水平拆分。两种拆分应用场景不同:垂直拆分是指按照业务模块进行拆分。简单来说,就是将业务关闭模块的字段/表放在同一个数据库或服务器上。将不同业务的字段/表分开,拆分到不同的数据库或服务器中。例如,在一个游戏系统中,玩家的基本信息和物品公会等信息是可以拆分的。如示例所示:(图片来源网络)横向拆分是指纯粹按照一定的数据规则/格式进行拆分。比如按照数据唯一ID的hash拆分,按照数据的日期拆分,按照一定的范围拆分等等。需要注意的是,在水平拆分中,由于数据动态变化,可能需要动态调整分片数量。另外,水平分片没有考虑业务特性,所以在分片中进行业务汇总查询或事务处理时,有时会比较麻烦。如图中示例:另外,在实际应用中,一般将两种拆分模式结合使用,效果会更好。以上就是数据库性能优化的“数据读写分离”和“分库分库”方法。欢迎与我们交流。