数据库主从一致性问题

作者: Ferrari1001 | 来源:发表于2018-03-22 22:58 被阅读17次

    背景

        上一篇我写了为了处理高并发带来的数据库压力问题,引出了数据库读写分离技术。其思想总结为:一主多从、读写分离,冗余多个读库。然而存在一个明显的问题就是:从数据库同步数据的同时可能给业务方返回的是旧的数据,即所谓的脏读现象。如图所示:


    image.png

    【1】系统先对Master-DB进行了一个写操作,写主库;
    【2】很短的时间内并发进行了一个读操作,读从库,此时主从同步没有完成,故读取到了一个旧数据;
    【3】主从同步完成。
        为了解决主从同步一致性导致读取旧数据的问题,本文主要提出四种解决方案,仅供参考。

    解决方案

    方案一、读写都在主库
        显然,这是一种最简单的方法,读写全落在主库上,必然不会带来不一致问题。如图所示: image.png
    方案二、semi-sync(半同步复制)
        之所以会读取到旧数据,关键在于主从同步需要一个时间段,而读取请求可能刚好就发生在同步阶段。为了读取到最新的数据,需要等主从同步完成之后,主库上的写请求再返回。示意图如图所示: image.png

    【1】系统先对DB-master进行了一个写操作,写主库;
    【2】等主从同步完成,写主库的请求才返回;
    【3】读从库,读到最新的数据(如果读请求先完成,写请求后完成,读取到的是“当时”最新的数据)。
        显然带来的后果就是主库的写请求时延会增加,吞吐量会降低。

    方案三、数据库中间件
        借助中间件的路由作用,对服务层的读写请求进行分发,从而避免出现不一致问题。示意图如图所示: image.png

    【1】所有的读写都走数据库中间件,通常情况下,写请求路由到主库,读请求路由到从库;
    【2】记录所有路由到主库的key,在经验主从同步时间窗口内(假设是500ms),如果有读请求访问中间件,此时有可能从库还是旧数据,就把这个key上的读请求路由到主库;
    【3】经验主从同步时间过完后,对应key的读请求继续路由到从库
        中间件带来的好处就是能保证数据的绝对一致性,但同时也带来成本上升的问题。

    方案四、利用缓存
        原理同方案三类似,当写请求发生时, image.png

    【1】将某个库上的某个key要发生写操作,记录在cache里,并设置“经验主从同步时间”的cache超时时间;
    【2】修改数据库

    而读取请求发生的时候: image.png
    从图中可以看出:
    1)先到cache里查看,对应库的对应key有没有相关数据;

    2)如果cache hit,有相关数据,说明这个key上刚发生过写操作,此时需要将请求路由到主库读最新的数据;
    3)如果cache miss,说明这个key上近期没有发生过写操作,此时将请求路由到从库,继续读写分离。
        显然,利用缓存,减少了中间件带来的成本问题,但多了一个Cache组件,并且读写数据库多了一步Cache操作,操作相对其他稍较繁琐。

    相关文章

      网友评论

        本文标题:数据库主从一致性问题

        本文链接:https://www.haomeiwen.com/subject/qhvzqftx.html