天天看点

数据密集型应用系统设计--数据复制简介主节点与从节点复制滞后多主节点无主节点

简介

引入数据复制的原因:

  1. 数据距离用户更近,让用户访问延迟降低
  2. 提高容错机制,某个节点坏掉后,其备份节点仍然能提供服务
  3. 负载扩展到多台机器,提高吞吐量

复制技术的真正难点在于如何处理持续变更的数据。

主节点与从节点

主从复制:

  1. 指定某个副本作为主副本,客户端全部写入主副本,更新主副本本地存储。
  2. 主副本把数据发送给从副本,从副本严格按照主副本发来的操作顺序,操作本地存储的数据
  3. 客户端可以从所有的副本中读取数据

同步复制: 主节点发送给从节点数据后,需要等从节点回复

异步复制: 主节点发送给从节点数据后,不必等从节点回复

同步复制,如果由于某些原因,导致主节点一直没有收到从节点的回复,那么后续的复制操作会阻塞。不过,同步复制逻辑简单,主节点发生故障后,任何一个从节点都可以当主节点。

异步复制,IO 非常高效,但是从节点会存在数据滞后的问题,主节点挂掉后,数据丢失。

半同步复制:有一个从节点保持和主节点同步操作,其余的从节点才用异步操作。相当于有个备份的主节点

配置新的从节点: 主节点定时 dump 数据快照,在下一次 dump 数据快照之前,保留更改的操作日志。新的从节点加入后,先发送数据快照,然后再发送更改日志即可。像 redis 之类的备份操作,都是这么做的。

实现复制日志:

  1. 基于语句的复制:复制

    INSERT DEL

    等更改语句,然后把对应的语句发送给从节点。实现简单,但是缺陷在于

    RNAD NOW

    等与环境有关的命令没有意义。
  2. 基于 WAL 预写日志:对于 SSTable 或者 LSMT 的方式,保留 追加的 write 日志,然后发送给从节点即可。适用于追加模式的数据库。
  3. 基于行的逻辑日志复制:类似于 MySQL 的 binlog,复制与存储分离。

复制滞后

复制滞后的问题,一般是暂时的,异步复制最终会一致,称之为『最终一致性』

**读自己的写:**写入主副本,但是读的从副本还没同步完数据

**单调读:**用户获取的数据的时间戳顺序不对。比如 A、B、C 3个对等机器,用户的请求路由到了3个机器上,A 中存在 x 用户的评论,但是 B C 中没有,A 返回了结果,B、C 也返回了结果,但是 B、C 的结果覆盖了 A 的结果,导致用户看到的评论消失了。

**前缀一致性:**用户获取的数据的时间戳是乱序的

多主节点

多个主节点,每个主节点同时是其他主节点的从节点。这些主节点,有自己的私有从节点。

场景:

  1. 多个数据中心同步数据
  2. 用户多个设备,比如一个用户有mac、iphone 和 ipad 这样的场景。这些设备可以离线
  3. 协作编辑

多主节点最难解决的是写入冲突的问题,一般来说最佳方案是避免冲突,其余方案这里暂时不涉及。

多主节点的拓扑结构:

  1. 环状拓扑
  2. 星式拓扑
  3. p2p 模式

    1和2的模式,最麻烦的地方在于关键路径损坏的话,会干扰整个集群的同步

无主节点

无主节点的方式,放弃主节点,允许客户端直接写入所有的结点。

客户端写入的时候,向多个副本写入数据。读取的时候,从多个副本读取。

  1. 读修复:假设某个节点下线后重新上线,其中的数据落后其他副本。则读取的时候,客户端会使用其他副本的数据,并更新当前落后节点的数据
  2. 反熵过程:客户端读取的时候,把其他副本中存在的数据,写入一个或者多个不存在数据的副本

假设 w 是一次性写入的副本个数,r 是一次性读取的副本的个数,n 是总的节点的个数,那么需要满足:w + r > n

w + r > n 通常可以配置,可以计算能容忍的坏节点的个数。

w + r 风格的局限性:

  1. 同时写入的情况,无法确认先后顺序
  2. 读写同时发生时,读的数据可能仍然是就值,因为写操作可能只是发生了一部分
  3. 某些副本写失败,整体操作认为失败,但是仍然有部分节点是成功的,此时读脏数据

继续阅读