一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第25天,点击查看活动详情。
为什么需要读写分离?
我们带着这个问题,往下学习。首先来看一个例子,这个例子又围绕着商品中心来展开了。那对于商品这种场景来说,我们通常来讲发布一个新商品或者修改商品。那这是一个在数据库当中的写入操作,或者 update 操作、insert 操作,更多的业务场景则是围绕着读取商品来展开。
很多的营销玩法、搜索等等,它其实都是对商品的读取。而对于商品的写入操作,其实场景很少,它只是集中在发布商品,设置商品的价格等等。
那这两者进行一个比较,我们发现一个场景更能成为数据库的性能瓶颈呢?
非常的显然意见,是读取商品读操作,这就是一个典型的读多写少的业务场景。那如何解决这种业务场景的性能瓶颈呢?答案呼之欲出,就是我们的读写分离。
读写分离的这种业务模式相信大家都非常熟悉了。那对于像 MySQL 这种数据库来说,通常有一个主库,我们叫它 master,在主库下面有 Slave1、Slave2、Slave3 这三个读库。主库和读库之间通过一种 bin log 的机制来做备份。我们对所有数据的写入操作直接操作在主库上面。那读取的操作则是的读库上面。
这种业务场景下,随着你的读请求越来越多。比如商品中心,这个业务平台上面有了更多的客户,客户都来去查看你的商品,自然而然读取请求就会变得增多。这种情况下,我们通常只需要去通过水平扩展的方式来把它的读库增加新的节点,就能非常容易的去解决性能瓶颈。因此这就是读写分离的目的。
通过读写分离,还有一个额外附赠的好处是什么?读库如果挂掉了,因为你的读取压力特别大,把整个读库集群打崩了,这种情况下它不会影响到 master 节点,写入请求依然可以去正常的操作。这是读写分离的一个显而易见的好处。
这里介绍的只是一个表象。其实咱们读写分离开来的一个原因,就是它们俩会相互拖累。怎么相互拖累呢?假如你的读和写请求,这里都落到了主节点,就是 master 节点。大家可知道,当你在 Write 的时候,也就是写入一条数据的时候,其实它在后台的数据库层将会给它上一个排它锁,排它锁就是我们俗称的写锁。
当一个数据被使用上了一个写锁,那么直到这个锁被释放之前,都不能去修改或者读取这个数据。因此才说它是一个排它锁。
对于 read 请求来说,它就温和了很多。read 请求会给一个数据加上共享锁。共享锁我们把它称作读锁。一个数据呢被加上读锁之后,那你其他的事物只能对它加同样的读锁,而不能去给它加一个排它缩。这就保证了你这条数据只能被各种共享的线程来读取而不能被修改。
那从上面的这个描述当中,我们能看出这两个锁之间有一个什么关系呢?它们之间是一个互相竞争的关系。
那如果我们人为的通过这种读写分离的方式,把这两种锁隔开,自然而然的就消除了这种竞争。那这就是我们读写分离性能比较高的一个原因之一。
读写分离虽好,我们怎么来用呢?有一种实现方式,在自己的代码里,如果发现它是一个 select 语句,就把它导向读节点,即 Slave 节点。如果发现是一个 update 或 insert 语句,把它导向 master 节点,这能不能完成任务呢?其实是可以的,但是这样增加了开发量。这个实现方式其实既不优雅,而且也增加了开发成本。
优雅的实现方式是什么呢?我们就是采用第三方工具 Sharding-Proxy 或者 Sharding-JDBC。通常我们在自己的项目当中会运用这类工具,将读请求导向 slave,把写请求导向到 master 当中。
这一部分具体的细节以及落地案例,我们会在后面数据库设计这一个单独的章节跟同学们详细解读。大家可以期待一下。这里呢只是跟大家抛砖引玉,让大家有这样的一个知识的铺垫。ok 那在前面在开始课程的时候,是不是跟同学们讲过啊,老师这里有一些对读写分离的不一样的解读。哎,那这里啊就要跟同学们说一下啊,
读写分离在传统的概念上面,它就是指数据库,但是缓存和搜索引擎它本质上也是一种读写分离。大家可能不信了,基于大家以前的工作经验当中,缓存好像还要自己控制读写。
比如这样的一个场景,我们有数据库、ES、Redis、OpenSearch、Solr 这种搜索引擎或者是缓存。在代码当中是不是都有这样的痛苦的经历,第一步先去读取这些 nosql 的 database,如果读取不到,再去真正的数据库里把这个数据给它读取出来,然后再把数据写入进去。
这种编程体验来,大家觉得这是读写分离吗?完全不是啊,原因是要再控制这个代码的,从哪儿读,从哪儿写,怎么样同步,这个过程都是代码来控制的。
读写分离缺点
读写分离在某些层面上有一些死角,假如现在是一个小平台在卖商品,例如刚刚起步的创业公司,商品的用户也不多。因此商品中心的数据只有五十万左右,master 节点有五十万,它同步到各个 slave 节点,也有五十万,每一个 slave 都有五十万。后面突然拿到了一笔大型电商平台的投资,此时,该创业公司的这个平台的业务大幅增加。来我这个平台买卖东西的商家也越来越多。因此这个商品数量从五十变到了五百万。
那这样一来,每个 slave 下面都有五百万的数据,这些数据都存在硬盘上面,但是对于像数据库这种的物理存储来说,单表记录如果超过了一定的数值,那它的性能会显著的降低。查询写入都会逐渐的玩不转。
那这种情况下有什么破解之道吗?如何来改进这种读写分离的架构,解决这样的问题呢?我们下期再见。