《设计数据密集型应用》- Designing Data-Intensive Application - 第5章 复制 读书笔记

14 篇文章 0 订阅
10 篇文章 0 订阅

在这里插入图片描述

复制

领导者与追随者

单领导者

同步复制与异步复制

  • 同步
  • 异步
  • 半同步:一个副节点同步,其余副节点异步

设置新从库

  • 全量镜象+增量

处理节点宕机

  • 从节点

    • 追赶恢复
  • 主节点

    • 流程

      • 由剩余从节点或控制节点进行选主流程
      • 通常选举有最新副本的从节点做为主节点
      • 旧主节点上线后作为从节点
    • 存在问题

      • 新主库缺失旧主库部分写入,如果其收到冲突的写入(如主键冲突),常见方法是丢掉旧主库未同步的写入,但影响了写入的持久性
      • 如果丢掉的写入与其他数据库相关联,则有可能会出现数据不一致的问题
      • 脑裂
      • 主库判定失效超时时间设置困难,太短,容易受网络抖动延迟误操作;太长,选主延迟加大,丢失的数据也可能越多

复制日志的实现

  • 基于语句的复制

    • 问题

      • 非确定语句运行会出现主从不一致的问题,如NOW(),RAND()
      • 如果使用了自增列或依赖于库中现有的数据,则从节占的执行顺序必须严格按主节点的执行顺序
      • 现MYSQL会将含有不确定的语句转换为基于行的复制
  • 基于WAL,PostgreSQL与Oracle使用该类复制

    • 问题:日志记录过于底层,记录了磁盘块上哪些字节有了更改,对主从所采用的存储引擎、数据库版本的一致性要求高
  • 基于逻辑日志(基于行)

    • 记录与存储引擎相分离,因此主从可采用不同的存储格式,数据库也可不同
  • 基于触发器

    • 由于事务需要等触发器完成其操作才能提交,所以事务处理延迟会增加。

复制延迟问题

解决方法

  • 读己之写

    • 从业务代码上入手

      • 对于和自身相关的信息,都从主库读取,其它用户的从从库读取

      • 跟踪上次更新时间,如果小于一定时间(如一分钟),则从主库读

      • 客户端保存最近一次写入的时间戳,所读的从库确保最新的数据时间大于等于该时间(访问需要系统额外判断从库数据的时间信息)

        • 如果同一用户在不同终端同时登录并做了写入操作,此时不同客户端所保存的时间戳不一致,也会出现所看到的数据不一致问题,在多数据中心的情况下情况更复杂
  • 单调读

    • 为防止两次读取从库可能出现的时间倒流情况(第一次读较新的库,第二次读了较旧的库),可使用户只在一个从库上读,确保数据单调一致性。(如根据用户ID进行HASH)
  • 一致前缀读

    • 为防止具有先后因果的数据所写入不同分区,而“因”数据的读入延迟大于“果”的读入延迟,在客户端侧看来会出现因果倒置于的现象,需要将具有前后因果的数据写入同一分区解决

多主复制

优势

  • 性能:写操作可以在本地数据中心进行处理,写网络延迟可能更低

  • 可用性

    • 容忍单个数据中心停机

    • 数据中心间采用异步复制,因此中心间的网络通信故障不会导致写入失败

      • 需要考虑的问题:写冲突
  • 其它适用的场景

    • 协同编辑

      • 如石墨文档
    • 离线场景

      • 考虑手机,笔记本电脑和其他设备上的日历应用。无论设备目前是否有互联网连接,你需要能随时查看你的会议(发出读取请求),输入新的会议(发出写入请求)。如果在离线状态下进行任何更改,则设备下次上线时,需要与服务器和其他设备同步
    • 专为多主设计的数据库CouchDB

      • CouchDB支持双向数据复制,冲突检查。其适用于文中的离线操作场景主要是受益于CouchDB的支持MVCC(多版本并发控制)特性,详见第7章。

写冲突

  • 如果采用同步冲突检测,即等待所有主节点写完毕告诉用户写成功,会失去各主节点可以独立写的优点

  • 避免冲突

    • 如同一用户所接入的写数据中心只能是同一个,如果允许同一用户的写请求同时接入多个数据中心,则需要在业务层面处理冲突
  • 冲突合并

    • 给每个写入分配一个ID(如时间戳),具有最新的ID胜出,丢弃其它写请求。

      • 易造成数据丢失
    • 给每个副本分配一个副本ID,具有最高ID的优先级高

      • 易造成数据丢失
    • 增加业务处理冲突代码

      • 写时执行

        • 检测到写冲突就调用用户自定义的处理代码。如Bucardo可编写Perl代码解决冲突
      • 读时执行

        • 写入时,所有冲突均会记录,待用户读时,返回多版本给应用,用应用决定处理
  • 复制拓扑

    • 环形

    • 星形

    • 互联(All to All)

      • 问题:如果出现了因果数据写入,则可能会出现类似于分片时延不同而导致的数据乱序问题

        • 解决方法:使用“版本向量”技术控制

无主复制

定义:由客户端同时向多个副本写入数据,由客户端决定写入是否成功,读取时根据各副本的版本号投票决定读取的结果

故障时写入数据库

  • 例子:假设3副本的环境,有一个副本不可用,2个副本可以正常写入

  • 读修复和反熵

    • 读修复:在客户端读取时向老版本的副本库中写入新的数据
    • 反熵:数据库后台检测旧版本,并对其数据进行修复
  • 读写的法定人数

检测并发写入

  • 单副本:使用基于版本号的乐观锁进行写入
  • 多副本:基于版本向量
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值