基本概念
数据的复制指的是通过网络链接的多台机器保留相同的副本
- 为什么要进行数据的复制
- 使得用户和数据在地理上比较接近,因为大数据要求我们将计算安排在数据存放的位置和我们基本的内存模型不是很一样 ,比如磁盘调入内存之类的。
- 即使系统的一部分机器出现了故障,系统也能正常工作,这个指的是如果一个节点出现宕机,应该怎么处理才能使系统正常工作。
- 扩展可以接收读请求机器的数量,如果有很多个机器进行读,如果只有一个副本的话,那么系统就会发生崩溃,有点类似于DNS泛洪攻击的原理。
领导者和追随者的复制
我们这里假设的情景是基于领导者的复制或者是说主从库的复制。
- 副本的概念:
当有多个副本的时候我们会思考几个问题,当存储多个副本的时候如何确保所有的数据落到所有的副本上,就类似于通知从教学秘书下放到计算学部大群, 我们到底是采用让所有的同学向教学秘书确认他收到消息了才算下放完成,还是说让辅导员老师通知班长下放消息 然后反馈给教学秘书我已经全通知完了。 - 同步和异步的优劣
同步的好处是可靠性很高 但是缺点是消耗资源,异步的优点
我们发现follower1的复制是同步的 但是2的复制是异步的 - 半同步
实际上 数据库大多是采用半同步复制的策略,也就是上面的图展示的样子,指定一个主库,并且从中指定一个从库使得主库和从库的复制是同步的,主库和其他从库的复制是异步的。这样的好处是如果一个主库发生的宕机,那么我们指定好了一个新的主库之后就把这个同步的从库的内容直接复制过去就行了。 - 半同步背景下,节点的加入节点的宕机复制日志的实现细节
我们采用比较多的是半同步复制,那么我们不妨看下底层的具体是如何实现的
由于大数据具有实时性的特点,任何时候都可能发生数据的更新,所以我们从库拉取的数据也未必是最新的数据,我们的数据库需要进行如下处理:首先拉取主库的一致性快照,快照复制到新的从库节点,然后将这些快照复制到新的从库节点,之后从库连接主库,并拉取复制快照之后的所有变更,这样新的节点就赶上主库了。
系统中任何的节点都可能宕机:包括主库 从库1 从库n也就是大老板 小老板 打工人都有可能出现故障,如果是从库发生故障 那么解决的方法非常简单,就是和新加入的节点的方法类似,首先修好之后,从库连接主库,并拉取宕机之后的日志,完成追赶。。主库发生故障这个问题是非常棘手的,首先我们需要考虑选谁充当主库,这个可以通过选举产生,也就是统计相同副本数量的个数来选举其次有可能出现两个或者多个从库同时充当主库的情况(类似于汉高祖失去权力之后 各路诸侯纷争)这个时候就会出现一个脑裂的情况,解决方法很粗暴如果两个的话随机关闭一个。还有一个问题就是可能会存在冲突的写入,老领导回来之后可能会产生冲突的写入,避免冲突写入的方法就是忽略老节点的写入,但是这样会破坏数据的持久性写入的原则。
- 日志的复制:
- 基于语句的复制:主库想要写入什么内容,比如情景是关系数据库update或者是delete之类的语句,但是这样可能会产生一想不到的后果,比如我让你们寝室的人都去老师那签到,本来老师以为是239的人是小明和小方,但是这两个人串寝室了,所有结果是小红和小绿去老师那报道了,所以除非有特别确定的结果,基于语句的复制是不好的。
- 传输预写日志:缺点是需要和存储引擎打交道,时间开销比较大。
- 逻辑日志的复制:基于行的复制,有利于向后兼容不同的数据库存储软件。
- 基于触发器的复制:
复制的延迟
- 复制的另外一个原因是适用于读多写少的情景,我们回顾一下 数据库更新的过程,如果一个客户想要往数据库写数据,首先发送请求给领导者,领导者收到数据之后写入其本地的存储,从库也被称作是只读副本,他不会直接读取数据,领导者将新的数据变更发送给所有的追随者,也就是复制日志记录,每个追随者拉取日志更新更新本地的数据库副本,那么就回到了我们数据复制的第三点原因,扩展可读机器的数量。
- 最终一致性,在不发生错误的情况下 主库和从库数据保持一致性的状态叫做最终一致性。
- 读己之写,我们写入数据库之后想要快速的看到自己的更新,一种方法是直接看自己从主库,看别人从其他的库读,第二种方法是检测状态。
多主复制
- 数据中心内部:采用主从复制的原则
- 数据中心之间:采用多主复制的原则
对比内容 | 单主复制 | 多主复制 |
---|---|---|
出现故障时 | 故障切换让数据中心的一个追随者成为领导者 | 每个数据中心可以独立于其他数据中心运行,并且发生故障时的数据中心归队时复制会自动赶上 |
容忍网络 | 敏感,因为写操作是同步的 | 临时的网络中断不影响写入 |
应用场景 | 离线的客户端 |
并发控制,当多个人写入的时候可能存在冲突解决的方法是加锁 或者是根据时间戳设置ID 或者是在读取的时候设置限制。