数据复制一(主从复制详解)

news2024/11/25 16:37:16

目录

一、主从复制

二、同步复制和异步复制

三、节点失效处理方案

四、复制日志的实现

五、复制滞后问题

读自己的写

单调读

前缀一致读


数据复制就是相同的数据在多台机器上传输,多台机器可以在一个机房也不可以跨区域。通过数据复制有以下好处:降低访问延迟(数据复制到离用户更近的地方)、当机器出现故障时,可以切换到副本机器,从而提高可用性、多台机器可以同时提供服务,从而提高吞吐量。

现在计算机技术来说数据复制就几种方法:主从复制、多主复制和无主节点复制。

一、主从复制

我们常用的很多中间件比如Mysql 以及 Redis 还有消息队列如kafka 都有主从复制,虽然他们的日志不一样,比如Mysql是通过binlog日志,Redis 是通过RDB 完成主从复制。KafKa 和他们完全又不一样,是通过生产者之间把消息写到主副本以及从副本,这个单独谈的。

主从复制工作原理可以总结如下:

  1. 通过配置去确定主从节点,主副本首先将数据写入本地存储

  2. 从副本和主副本进行网络连接后,主副会把新数据写入到本地存储后,然后将数据更改作为复制的日志或更改流发送给所有从副本。每个从副本获得更改日志之后将其应用到本地,且严格保持与主副本相同的写入顺序。

  3. 客户端读取数据时可以从主从节点读取数据,为啥会从主节点读取数据呢,一些特殊情况比如说Mysql的事务,从节点可以由于网络或者负载可能并不能有最新的数据,所以需要从主节点读。从节点只能读不能写。

主从复制又分为同步复制和异步复制,对于关系数据库系统如mysql ,可以配置同步复制还是异步复制,其他的系统需要根据官网文档查看

从上图可以看出节点1是同步复制,主节点需要等待节点1返回信息才能像用户1234反馈是否成功,节点2是异步,主节点不需要等待节点1返回信息。

二、同步复制和异步复制

同步复制的优点:一旦向用户确认,那么可以保证所有的数据都同步完成与主节点的数据是一致的,缺点也是很明显的,从节点出现故障比如网络故障、节点崩溃等。那么主节点将会堵塞,会影响真个系统的性能。一般都会设置成半同步,不管出现何等情况,比如说同步从节点故障,可以把其他的一些异步的从节点设置成同步的从节点,这样至少有一个节点是同步从节点,主从切换的时候,可以保证数据不会丢失。

全异步模式:优点就是主节处理数据的速度很快,系统吞吐快。缺点就是主节点发生故障不可恢复,从节点没有完成数据的同步,进行主从切换,数据丢失了,无法保证数据的持久化。这听起来不靠谱,但是对于多主复制来说,有些主节点在不同区域,还是有广泛应用的。

如果我们增加了新的从节点,可能是为了增加容错能力也可能是替换失效的副本,那么新节点与主节点如何保证数据的一致呢?

我这里首先想到了一种解决方案,直接把主节点的数据或者日志文件直接拷贝到新的从节点,不可以的,主节点还是不断的从客户端更新数据,新节点的数据与主节点的数据就会不一致。不一致好办呀,直接主节点离线或者给主节点设置成readonly 等同步完成后在上线或者设置成读写,这样会影响整个系统的性能,无法完成业务。

正确的做法应该是这样的:

  1. 在某个时间点对主节点的数据副本产生一个一致性快照,这样避免长时间锁定整个数据库。目前大多数数据库都支持此功能,快照也是系统备份所必需的。而在某些情况下,可能需要第三方工具,如MySQL 的innobackupex

  2. 将此快照拷贝到新的从节点。

  3. 从节点连接到主节点并请求快照点之后所发生的数据更改日志。因为在第一步创建快照时,快照与系统复制日志的某个确定位置相关联,这个位置信息在不同的系统有不同的称呼,如PostgreSQL 将其称为“log sequence number” (日志序列号),而MySQL 将其称为“bi nlog coordinates”, redis 是offset 。

  4. 获得日志之后,从节点来应用这些快照点之后所有数据变更,这个过程称之为追赶。接下来,它可以继续处理主节点上新的数据变化。井重复步骤l ~步骤4

三、节点失效处理方案

如果节点失效该怎么处理:

从节点失效:追赶式恢复

从节点的本地磁盘上都保存了副本收到的数据变更日志。如果从节点发生崩愤,然后顺利重启,或者主从节点之间的网络发生暂时中断(闪断),则恢复比较容易,根据副本的复制日志,从节点可以知道在发生故障之前所处理的最后一笔事务,然后连接到主节点,并请求自那笔事务之后中断期间内所有的数据变更。在收到这些数据变更日志之后,将其应用到本地来追赶主节点。之后就和正常情况一样持续接收来自主节点数据流的变化。

主节点失效:节点切换

主节点失效了,选择一个从节点作为主节点,完成主从切换,这个步骤可以是手动的也可以是自动切换。具体的步骤如下:

  1. 确定主节点失效。现在都是采用超市机制:节点间频繁地互相发送心跳存活消息,如果发现某一个节点在一段比较长时间内(例如30s)没有响应,并且在半数以上节点都发现某个节点没有响应,认为该节点失效

  2. 选出新的主节点方式有很多种比如Raft、paxos,etcd 用的就是Raft。节点间相互投票,可以根据数据的差异大小、机器的配置等打分,分数最高的就是新的主节点

  3. 确定新的主节点后就进行切换,客户端以后就往新的主节点写数据,如果原来的主节点上线连接到集群,发现有主节点,自动降级为从节点

上面的步骤充满了很多的变数

  1. 使用的异步复制并且在失效之前,新的主节点并没有收到原主节点的所有数据;在选举之后,原主节点很快又重新上线并加入到集群,新的主节点可能会收到冲突的写请求。这是因为原主节点未意识的角色变化,还会尝试同步其他从节点,但其中的一个现在已经接管成为现任主节点。常见的解决方案是,原主节点上未完成复制的写请求就此丢弃,但这可能会违背数据更新持久化的承诺。丢失数据也不是一个明智的选举如果数据表的主键 作为redis 的key,还可能造成数据的覆盖

  2. 由于网络问题,可能会有两个节点同时认为自己是主节点这种情况称为脑裂,非常危险:两个节点都可能接受写请求,并且没有很好解决冲突的办法,最后数据可能会丢失或者破坏。这种情况就必须强制关闭一个节点。

  3. 设置合适的超时时间检测主节点失效呢,设置过长,意味着切换时间过长,设置时间太短,导致不必要的切换,例如突发的负载峰值会导致节点的响应时间变长甚至超肘,或者由于网络故障导致延迟增加。如果系统此时已经处于高负载压力或网络已经出现严重拥塞,不必要的切换操作只会使总体情况变得更糟。

四、复制日志的实现

  1. 基于语句的复制:主节点记录所执行的每个写请求(操作语句)井将该操作语句作为日志发送给从节点。对于关系数据库,这意味着每个INSERT、UPDATE 或DELETE 语句都会转发给从节点,并且每个从节点都会分析井执行这些SQU 吾句,如同它们是来自客户端那样。对于mysql 来说 binlog 是 statement 模式。这种模式日志好处是小并且看起来很明了。

    也有一些不使用的场景如下:

    • 比如说sql 语句有now()以及Rand(),主从数据就不一致。

    • 如果语句使用了自增列,或者依赖于数据库的现有数据(例如,UPDATE ... WHERE 条件)所有的副本必须按照完全相同的顺序执行,否则会出现不同的结果。

    • 如果有副作用语句(触发器、存储过程、用户自定义函数)可能在每个副本产生不同的副作用

  2. 基于预写日志(WAL)传输

    这种日志格式主要有以下两个方式:

    • 对于日志结构存储引擎(SSTables 和L SM - trees ),日志是主要的存储方式。日志段在后台压缩井支持垃圾回收。

    • 对于采用覆盖写磁盘的Btree结构,每次修改会预先写入日志,如系统发生崩愤,通过索引更新的方式迅速恢复到此前致状态。

    所有对数据库写入的字节序列都被记入日志,然后把这些日志通过网络发送到其他从节点构建数据 这种方式好处是它记录的是磁盘块的那些字节发生了改变,非常底层,节约磁盘空间,坏处也很明了,主从节点必须是相同的存储引擎,这么说也不对,只是说相同的存储引擎具有相同的存储格式。

    这种格式在mysql 内部用的比较多也就是先写日志在刷盘,主从之间一般不会这么用,但是理论上也是可以的,只是缺点大于优点

  3. 基于行的逻辑日志复制

    对于mysql 来说这种模式就是binglog 是row 模式。日志里面记录的是数据:

    • 对于行插入,日志包含所有相关列的新值

    • 对于行的删除,日志里有足够的信息来唯一标识已删除的行,通常是靠主键,但如果表上没有定义主键,就需要记录所有列的旧值。

    • 对于行更新,日志包含足够的信息来唯一标识更新的行,以及所有列的新值(或至少包含所有已更新列的新值)。

    • 如果一条事务涉及多行的修改,则会产生多个这样的日志记录,并在后面跟着一条记录,指出该事务已经提交

    这种方式有很多优点:

    • 日志和存储引擎解藕,也就意味着主从节点可以是不同的存储引擎以及不同的版本

    • 由于是数据,我们可以通过CDC 技术把数据异步同步到Redis 或者 ES 或则数据仓库 对数据进行分析以及实现搜索功能

  4. 基于触发器的复制 可以用户自定义触发器,把部分数据写到其他的表中,也是非常方便的

五、复制滞后问题

主从复制我们不可能把所有的节点都设置成同步,所以就有一个特别,异步同步的节点会有一个特性最终一致性,最终是多久呢,我也不知道,可能与你的网络以及负载有关。那么就会有一个现象,用户可能看不到自己提交的数据,也可能一会看到一会看不到。对于这样的方式有没有什么好的解决方案

读自己的写

也就是说用户读自己的数据是在主节点读,其他人读数据在从节点读也就是所谓写后读一致性也称为读写一致性,保证当前用户总是能立刻读到自己写的数据,其他用户可能会稍后读到相关数据。

这种方式有以下几种方案:

  1. 如果用户访问可能会被修改的内容,从主节点读取;否则,在从节点读取。这背后就要求有一些方法在实际执行查询之前,就已经知道内容是否可能会被修改。也就是说是自己可以修改的内容,内容所有者是自己

  2. 对于第一点是有问题的,如果大部分内容都可能被所有者修改,都读主节点,主节点负载会很高,就失去了意义。我们可以根据数据修改的时间,最近一分钟修改的话从主节点读,其他的从节点读。我们可以在redis 记录数据修改时间也可以在客户端记录数据修改的时间,传给服务端。都是通过 proxy 选择节点去读数据

  3. 如果副本分布在多数据中心(例如考虑与用户的地理接近,以及高可用性),情况会更复杂些。必须先把请求路由到主节点所在的数据中心(该数据中心可能离用户很远)

单调读

还有一种情况是多个副本他们同步速度不一样,用户1先从副本1读取到了数据,刷新页面从副本2没有读取到数据。那是不是很懵逼,用户莫名其妙,就可以用单调读。

单调读一致性可以确保不会发生这种异常。这是一个比强一致性弱,但比最终一致性强的保证。当读取数据时,单调读保证,如果某个用户依次进行多次读取,贝l j 他绝不会看到回攘现象,即在读取较新值之后又发生读旧值的情况。

实现方式很简单,在读从节点的时候,通过用户id的hash总是路由到同一副本

前缀一致读

对于那些需要保证事件的先后顺序比如聊天,A聊天了B回。不管怎么读总是这个顺序,有一种反常现象是看到B回然后是A。这种情况通常在分布式数据库,数据写在不同分区上。就不存在全局写入顺序。解决这个问题就必须用到前缀一致读。

前缀一致读,该保证是说,对于一系列按照某个顺序发生的写请求,那么读取这些内容时也会按照当时写入的顺序。一个解决方案是确保任何具有因果顺序关系的写人都交给一个分区来完成,但该方案真实实现效率会大打折扣。现在有一些新的算法来显式地追踪事件因果关系。

接下来文章将在数据复制二讲解多活

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2061347.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

「数组」希尔排序 / 区间增量优化(C++)

目录 概述 思路 核心概念:增量d 算法过程 流程 Code 优化方案 区间增量优化 Code(pro) 复杂度 概述 我们在「数组」冒泡排序|选择排序|插入排序 / 及优化方案(C)中讲解了插入排序。 它有这么两个特点: ①待排序元素较…

<数据集>无人机航拍不同高度牧羊识别数据集<目标检测>

数据集格式:VOCYOLO格式 图片数量:6065张 标注数量(xml文件个数):6065 标注数量(txt文件个数):6065 标注类别数:1 标注类别名称:[sheep] 序号类别名称图片数框数1sheep6065149785 使用标注工具&…

【Spring】初识Spring MVC

文章目录 前言一、MVC是什么?二、学习Spring MVC建立连接RequestMapping注解注解的使用细节 三、传递参数的情况传递单个参数1.传递String2.传递包装类/基本类型3.参数重命名(RequestParam) 传递多个参数传递对象传递数组传递集合参数为变量传递文件小细节 四、JSON…

MCAL--MCU (S32K144)

AutoSAR中MCU Driver主要提供了用于基本的控制器初始化、下电、复位功能的服务,同时也为其它MCAL层需要的功能提供对应的服务函数。通常来说在AutoSAR的架构中MCU主要支持以下几个功能: 1.初始化控制器的外设时钟、系统时钟、PLL等,对所有控制器内各个外设模块用到的时钟提供…

Spring之@Bean注解

1. 使用方式 1.1 Configuration Bean 1.1.1 创建实体类 User Data NoArgsConstructor public class User {private String name;public User(String name) {this.name name;} } 1.1.2 创建配置类 UserConfig Configuration public class UserConfig {Beanpublic User us…

Web客户端软件测试

目录 1.测试分类 按照软件产生的阶段划分 按照代码可见度划分 其他测试 2.质量模型:衡量一个软件质量的维度 3.软件测试 1.单功能测试 等价类划分法:一种用少量数据获得较好测试效果的工具 边界值分析法:一个边界范围限制选取测试数…

最近云计算领域有哪些重大进展?

在云计算领域,近期确实涌现出了一系列令人瞩目的重大进展。以下是一些关键点,为您概述了当前的科技动态: 中国云计算市场迅猛发展: 中国云计算市场正处于快速发展期,年复合增长率超过40%。公有云市场规模增长49.3%至32…

深信达反向沙箱:构筑内网安全与成本效益的双重防线

# 深信达反向沙箱:内网安全与成本控制的双重保障 在数字化时代,企业面临着日益复杂的网络安全挑战。内网安全尤其关键,因为它涉及到企业的核心数据和运营。深信达的反向沙箱技术,作为一种创新的安全解决方案,为政企单…

厦门凯酷全科技有限公司:抖音小店前沿的探索者与引领者

在数字经济浪潮席卷全球的今天,电商平台已成为推动消费升级、激发市场活力的关键力量。其中,抖音作为短视频与直播电商的佼佼者,正以其独特的内容生态和庞大的用户基础,重新定义着零售行业的边界。在这一背景下,厦门凯…

学习记录——day33 HTTP

目录 一、HTTP相关概念 二、客服端请求 1、请求首部 2、 响应首部 三、线程实现HTTP并发服务器 一、HTTP相关概念 1、HTTP,全称Hyper Text Transfer Protocol,用于万维网(world wide web)进行超文本学习的传输协议 2、HTTP属…

如何使用 Java 记录简化 Spring Data 中的数据实体

Java 开发人员一直依赖 Spring Data 来实现高效的数据访问。但是,随着 Java Records 的引入,数据实体的管理方式发生了重大变化。 在本文中,我们将讨论 Java Records 在 Spring Data 应用程序中的集成。我们将探讨使用 Java 记录创建健壮的数…

CGAL 线性插值(自然邻近坐标)

文章目录 一、简介二、实现代码三、实现效果一、简介 自然邻近坐标插值(Natural Neighbor Interpolation)是一种基于Voronoi图的插值方法。它被广泛应用于地理信息系统(GIS)、计算几何以及科学计算领域。该方法的核心思想是利用数据点的Voronoi单元来确定插值点的权重,从而…

基于java的酒店管理系统设计与实现

系统分析与设计 需求分析 1.系统概要 根据餐饮系统的流程,完成从用户登录到开台点菜,到结账收银,到统计一条线的信息化管理,因此整个餐饮管理信息系统的研发内容就是开发一整套餐饮管理信息系统,实现餐饮业务的计算…

【三维重建】2D Gaussian Splatting:几何准确的2D辐射场(更新中)

标题:2D Gaussian Splatting for Geometrically Accurate Radiance Fields 项目地址:https://github.com/hbb1/2d-gaussian-splatting 文章目录 功能输入输出 一、摘要二、引言深入分析解读 三、相关工作3.1新视角合成3.2 3D重建3.3 可微分基于点的图形…

Manim动画:相机的移动(MovingCameraScene)

1.相机的移动(MovingCameraScene) MovingCameraScene 是 Manim 中的一个类&#xff0c;用于创建可以移动的相机场景。这个类继承自 Scene&#xff0c;并提供了关于相机移动的额外功能。 MovingCameraScene(camera_class<class manim.camera.moving_camera.MovingCamera>…

搭建ELK日志采集与分析系统

SpringCloud微服务实战——企业级开发框架 &#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您…

5.Linux_Shell编程

概述 什么是shell脚本&#xff1a; Shell脚本是利用shell的功能所写的一个程序。这个程序是使用纯文本文件&#xff08;后缀为.sh&#xff09;&#xff0c;将一些shell的语法与命令&#xff08;含外部命令&#xff09;写在里面&#xff0c;搭配正则表达式、管道命令与数据流重…

【QT代码控制Linux开发板】QT控制嵌入式Linux开发板运行shell脚本

一. 前言 最近遇到了一个很冲突的问题&#xff0c;我想让比如qt代码控制传感器读取的数值大于某个阈值时控制板子的灯亮进行报警。 但是当我在Linux开发板上./运行交叉编译后的qt文件时&#xff0c;想运行开发板的其他shell语句必须先退出qt代码的执行&#xff0c;当然开发板…

ios白苹果修复办法有哪些?

在这个数字化时代&#xff0c;iPhone作为智能手机的佼佼者&#xff0c;早已融入了我们生活的方方面面。然而&#xff0c;当那熟悉的开机画面——“白苹果”意外地成为了你的日常&#xff0c;无疑让人头疼不已。别担心&#xff0c;今天我们就来聊聊iOS白苹果现象的成因及几种有效…

Element-ui table进阶使用

最近项目有多个报表开发的需求&#xff0c;我采用的是凤翎前端组件框架&#xff08;基于element-ui开发&#xff09;&#xff0c;大伙可以直接参考element-ui组件库文档&#xff0c;把标签中的fks替换为el即可。下面我会按顺序一一展开细说这些需求&#xff1a; 1、有多级表头…